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