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