]> git.stg.codes - stg.git/blob - stglibs/srvconf.lib/netunit.cpp
9955d2e5e3e16cb9304fd341d6df352f5a9a5535
[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
29 #include "netunit.h"
30
31 #include "stg/servconf_types.h"
32 #include "stg/common.h"
33 #include "stg/blowfish.h"
34
35 #include <cstdio>
36 #include <cerrno>
37 #include <cstring>
38
39 #include <netdb.h>
40 #include <arpa/inet.h>
41 #include <unistd.h>
42
43 #include <sys/types.h>
44 #include <sys/socket.h>
45 #include <netinet/in.h>
46
47 using namespace STG;
48
49 namespace
50 {
51
52 const std::string::size_type MAX_XML_CHUNK_LENGTH = 2048;
53
54 }
55
56 //---------------------------------------------------------------------------
57
58 #define SEND_DATA_ERROR             "Send data error!"
59 #define RECV_DATA_ANSWER_ERROR      "Recv data answer error!"
60 #define UNKNOWN_ERROR               "Unknown error!"
61 #define CONNECT_FAILED              "Connect failed!"
62 #define INCORRECT_LOGIN             "Incorrect login!"
63 #define INCORRECT_HEADER            "Incorrect header!"
64 #define SEND_LOGIN_ERROR            "Send login error!"
65 #define RECV_LOGIN_ANSWER_ERROR     "Recv login answer error!"
66 #define CREATE_SOCKET_ERROR         "Create socket failed!"
67 #define WSASTARTUP_FAILED           "WSAStartup failed!"
68 #define SEND_HEADER_ERROR           "Send header error!"
69 #define RECV_HEADER_ANSWER_ERROR    "Recv header answer error!"
70
71 //---------------------------------------------------------------------------
72 NETTRANSACT::NETTRANSACT(const std::string & s, uint16_t p,
73                          const std::string & l, const std::string & pwd)
74     : server(s),
75       port(p),
76       login(l),
77       password(pwd),
78       outerSocket(-1),
79       RxCallBack(NULL),
80       dataRxCallBack(NULL)
81 {
82 }
83 //---------------------------------------------------------------------------
84 int NETTRANSACT::Connect()
85 {
86 outerSocket = socket(PF_INET, SOCK_STREAM, 0);
87 if (outerSocket < 0)
88     {
89     errorMsg = CREATE_SOCKET_ERROR;
90     return st_conn_fail;
91     }
92
93 struct sockaddr_in outerAddr;
94 memset(&outerAddr, 0, sizeof(outerAddr));
95
96 unsigned long ip = inet_addr(server.c_str());
97
98 if (ip == INADDR_NONE)
99     {
100     struct hostent * phe = gethostbyname(server.c_str());
101     if (phe == NULL)
102         {
103         errorMsg = "DNS error.\nCan not reslove " + server;
104         return st_dns_err;
105         }
106
107     struct hostent he;
108     memcpy(&he, phe, sizeof(he));
109     ip = *((long *)he.h_addr_list[0]);
110     }
111
112 outerAddr.sin_family = AF_INET;
113 outerAddr.sin_port = htons(port);
114 outerAddr.sin_addr.s_addr = ip;
115
116 if (connect(outerSocket, (struct sockaddr *)&outerAddr, sizeof(outerAddr)) < 0)
117     {
118     errorMsg = CONNECT_FAILED;
119     close(outerSocket);
120     return st_conn_fail;
121     }
122
123 return st_ok;
124 }
125 //---------------------------------------------------------------------------
126 int NETTRANSACT::Disconnect()
127 {
128 close(outerSocket);
129 return 0;
130 }
131 //---------------------------------------------------------------------------
132 int NETTRANSACT::Transact(const char * data)
133 {
134 int ret;
135 if ((ret = TxHeader()) != st_ok)
136     {
137     Disconnect();
138     return ret;
139     }
140
141 if ((ret = RxHeaderAnswer()) != st_ok)
142     {
143     Disconnect();
144     return ret;
145     }
146
147 if ((ret = TxLogin()) != st_ok)
148     {
149     Disconnect();
150     return ret;
151     }
152
153 if ((ret = RxLoginAnswer()) != st_ok)
154     {
155     Disconnect();
156     return ret;
157     }
158
159 if ((ret = TxLoginS()) != st_ok)
160     {
161     Disconnect();
162     return ret;
163     }
164
165 if ((ret = RxLoginSAnswer()) != st_ok)
166     {
167     Disconnect();
168     return ret;
169     }
170
171 if ((ret = TxData(data)) != st_ok)
172     {
173     Disconnect();
174     return ret;
175     }
176
177 if ((ret = RxDataAnswer()) != st_ok)
178     {
179     Disconnect();
180     return ret;
181     }
182
183 return st_ok;
184 }
185 //---------------------------------------------------------------------------
186 int NETTRANSACT::TxHeader()
187 {
188 if (send(outerSocket, STG_HEADER, strlen(STG_HEADER), 0) <= 0)
189     {
190     errorMsg = SEND_HEADER_ERROR;
191     return st_send_fail;
192     }
193
194 return st_ok;
195 }
196 //---------------------------------------------------------------------------
197 int NETTRANSACT::RxHeaderAnswer()
198 {
199 char buffer[sizeof(STG_HEADER) + 1];
200
201 if (recv(outerSocket, buffer, strlen(OK_HEADER), 0) <= 0)
202     {
203     printf("Receive header answer error: '%s'\n", strerror(errno));
204     errorMsg = RECV_HEADER_ANSWER_ERROR;
205     return st_recv_fail;
206     }
207
208 if (strncmp(OK_HEADER, buffer, strlen(OK_HEADER)) == 0)
209     {
210     return st_ok;
211     }
212 else
213     {
214     if (strncmp(ERR_HEADER, buffer, strlen(ERR_HEADER)) == 0)
215         {
216         errorMsg = INCORRECT_HEADER;
217         return st_header_err;
218         }
219     else
220         {
221         errorMsg = UNKNOWN_ERROR;
222         return st_unknown_err;
223         }
224     }
225 }
226 //---------------------------------------------------------------------------
227 int NETTRANSACT::TxLogin()
228 {
229 char loginZ[ADM_LOGIN_LEN];
230 memset(loginZ, 0, ADM_LOGIN_LEN);
231 strncpy(loginZ, login.c_str(), ADM_LOGIN_LEN);
232
233 if (send(outerSocket, loginZ, ADM_LOGIN_LEN, 0) <= 0)
234     {
235     errorMsg = SEND_LOGIN_ERROR;
236     return st_send_fail;
237     }
238
239 return st_ok;
240 }
241 //---------------------------------------------------------------------------
242 int NETTRANSACT::RxLoginAnswer()
243 {
244 char buffer[sizeof(OK_LOGIN) + 1];
245
246 if (recv(outerSocket, buffer, strlen(OK_LOGIN), 0) <= 0)
247     {
248     printf("Receive login answer error: '%s'\n", strerror(errno));
249     errorMsg = RECV_LOGIN_ANSWER_ERROR;
250     return st_recv_fail;
251     }
252
253 if (strncmp(OK_LOGIN, buffer, strlen(OK_LOGIN)) == 0)
254     {
255     return st_ok;
256     }
257 else
258     {
259     if (strncmp(ERR_LOGIN, buffer, strlen(ERR_LOGIN)) == 0)
260         {
261         errorMsg = INCORRECT_LOGIN;
262         return st_login_err;
263         }
264     else
265         {
266         errorMsg = UNKNOWN_ERROR;
267         return st_unknown_err;
268         }
269     }
270 }
271 //---------------------------------------------------------------------------
272 int NETTRANSACT::TxLoginS()
273 {
274 char loginZ[ADM_LOGIN_LEN];
275 memset(loginZ, 0, ADM_LOGIN_LEN);
276 strncpy(loginZ, login.c_str(), ADM_LOGIN_LEN);
277
278 BLOWFISH_CTX ctx;
279 EnDecodeInit(password.c_str(), PASSWD_LEN, &ctx);
280
281 for (int j = 0; j < ADM_LOGIN_LEN / ENC_MSG_LEN; j++)
282     {
283     char ct[ENC_MSG_LEN];
284     EncodeString(ct, loginZ + j * ENC_MSG_LEN, &ctx);
285     if (send(outerSocket, ct, ENC_MSG_LEN, 0) <= 0)
286         {
287         errorMsg = SEND_LOGIN_ERROR;
288         return st_send_fail;
289         }
290     }
291
292 return st_ok;
293 }
294 //---------------------------------------------------------------------------
295 int NETTRANSACT::RxLoginSAnswer()
296 {
297 char buffer[sizeof(OK_LOGINS) + 1];
298
299 if (recv(outerSocket, buffer, strlen(OK_LOGINS), 0) <= 0)
300     {
301     printf("Receive secret login answer error: '%s'\n", strerror(errno));
302     errorMsg = RECV_LOGIN_ANSWER_ERROR;
303     return st_recv_fail;
304     }
305
306 if (strncmp(OK_LOGINS, buffer, strlen(OK_LOGINS)) == 0)
307     {
308     return st_ok;
309     }
310 else
311     {
312     if (strncmp(ERR_LOGINS, buffer, strlen(ERR_LOGINS)) == 0)
313         {
314         errorMsg = INCORRECT_LOGIN;
315         return st_logins_err;
316         }
317     else
318         {
319         errorMsg = UNKNOWN_ERROR;
320         return st_unknown_err;
321         }
322     }
323 }
324 //---------------------------------------------------------------------------
325 int NETTRANSACT::TxData(const char * text)
326 {
327 int n = strlen(text) / ENC_MSG_LEN;
328 int r = strlen(text) % ENC_MSG_LEN;
329
330 BLOWFISH_CTX ctx;
331 EnDecodeInit(password.c_str(), PASSWD_LEN, &ctx);
332
333 char textZ[ENC_MSG_LEN];
334 char ct[ENC_MSG_LEN];
335
336 for (int j = 0; j < n; j++)
337     {
338     strncpy(textZ, text + j * ENC_MSG_LEN, ENC_MSG_LEN);
339     EncodeString(ct, textZ, &ctx);
340     if (send(outerSocket, ct, ENC_MSG_LEN, 0) <= 0)
341         {
342         errorMsg = SEND_DATA_ERROR;
343         return st_send_fail;
344         }
345     }
346
347 memset(textZ, 0, ENC_MSG_LEN);
348
349 if (r)
350     strncpy(textZ, text + n * ENC_MSG_LEN, ENC_MSG_LEN);
351
352 EnDecodeInit(password.c_str(), PASSWD_LEN, &ctx);
353
354 EncodeString(ct, textZ, &ctx);
355 if (send(outerSocket, ct, ENC_MSG_LEN, 0) <= 0)
356     {
357     errorMsg = SEND_DATA_ERROR;
358     return st_send_fail;
359     }
360
361 return st_ok;
362 }
363 //---------------------------------------------------------------------------
364 int NETTRANSACT::TxData(char * data)
365 {
366 char passwd[ADM_PASSWD_LEN];
367 memset(passwd, 0, ADM_PASSWD_LEN);
368 strncpy(passwd, password.c_str(), ADM_PASSWD_LEN);
369
370 char buff[ENC_MSG_LEN];
371 memset(buff, 0, ENC_MSG_LEN);
372
373 int l = strlen(data) / ENC_MSG_LEN;
374 if (strlen(data) % ENC_MSG_LEN)
375     l++;
376
377 BLOWFISH_CTX ctx;
378 EnDecodeInit(passwd, PASSWD_LEN, &ctx);
379
380 for (int j = 0; j < l; j++)
381     {
382     strncpy(buff, &data[j * ENC_MSG_LEN], ENC_MSG_LEN);
383     char buffS[ENC_MSG_LEN];
384     EncodeString(buffS, buff, &ctx);
385     send(outerSocket, buffS, ENC_MSG_LEN, 0);
386     }
387
388 return 0;
389 }
390 //---------------------------------------------------------------------------
391 int NETTRANSACT::RxDataAnswer()
392 {
393 BLOWFISH_CTX ctx;
394 EnDecodeInit(password.c_str(), PASSWD_LEN, &ctx);
395
396 std::string chunk;
397 while (true)
398     {
399     char bufferS[ENC_MSG_LEN];
400     size_t toRead = ENC_MSG_LEN;
401     while (toRead > 0)
402         {
403         int ret = recv(outerSocket, &bufferS[ENC_MSG_LEN - toRead], toRead, 0);
404         if (ret <= 0)
405             {
406             printf("Receive data error: '%s'\n", strerror(errno));
407             close(outerSocket);
408             errorMsg = RECV_DATA_ANSWER_ERROR;
409             return st_recv_fail;
410             }
411         toRead -= ret;
412         }
413
414     char buffer[ENC_MSG_LEN];
415     DecodeString(buffer, bufferS, &ctx);
416
417     bool final = false;
418     size_t pos = 0;
419     for (; pos < ENC_MSG_LEN && buffer[pos] != 0; pos++) ;
420     if (pos < ENC_MSG_LEN && buffer[pos] == 0)
421         final = true;
422
423     if (pos > 0)
424         chunk.append(&buffer[0], &buffer[pos]);
425
426     if (chunk.length() > MAX_XML_CHUNK_LENGTH || final)
427         {
428         if (RxCallBack != NULL)
429             if (!RxCallBack(dataRxCallBack, chunk, final))
430                 return st_xml_parse_error;
431         chunk.clear();
432         }
433
434     if (final)
435         return st_ok;
436     }
437 }
438 //---------------------------------------------------------------------------
439 void NETTRANSACT::SetRxCallback(void * data, RxCallback_t cb)
440 {
441 RxCallBack = cb;
442 dataRxCallBack = data;
443 }