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.
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.
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
18 * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
23 #include "stg/servconf_types.h"
24 #include "stg/common.h"
25 #include "stg/blowfish.h"
26 #include "stg/bfstream.h"
28 #include <algorithm> // std::min
36 #include <arpa/inet.h>
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <netinet/in.h>
48 const std::string::size_type MAX_XML_CHUNK_LENGTH = 2048;
53 NETTRANSACT::CALLBACK callback;
60 //---------------------------------------------------------------------------
62 #define SEND_DATA_ERROR "Send data error!"
63 #define RECV_DATA_ANSWER_ERROR "Recv data answer error!"
64 #define UNKNOWN_ERROR "Unknown error!"
65 #define CONNECT_FAILED "Connect failed!"
66 #define BIND_FAILED "Bind failed!"
67 #define INCORRECT_LOGIN "Incorrect login!"
68 #define INCORRECT_HEADER "Incorrect header!"
69 #define SEND_LOGIN_ERROR "Send login error!"
70 #define RECV_LOGIN_ANSWER_ERROR "Recv login answer error!"
71 #define CREATE_SOCKET_ERROR "Create socket failed!"
72 #define WSASTARTUP_FAILED "WSAStartup failed!"
73 #define SEND_HEADER_ERROR "Send header error!"
74 #define RECV_HEADER_ANSWER_ERROR "Recv header answer error!"
76 //---------------------------------------------------------------------------
77 NETTRANSACT::NETTRANSACT(const std::string & s, uint16_t p,
78 const std::string & l, const std::string & pwd)
87 //---------------------------------------------------------------------------
88 NETTRANSACT::NETTRANSACT(const std::string & s, uint16_t p,
89 const std::string & la, uint16_t lp,
90 const std::string & l, const std::string & pwd)
100 //---------------------------------------------------------------------------
101 NETTRANSACT::~NETTRANSACT()
105 //---------------------------------------------------------------------------
106 int NETTRANSACT::Connect()
108 sock = socket(PF_INET, SOCK_STREAM, 0);
111 errorMsg = CREATE_SOCKET_ERROR;
115 if (!localAddress.empty())
120 unsigned long ip = inet_addr(localAddress.c_str());
122 if (ip == INADDR_NONE)
124 struct hostent * phe = gethostbyname(localAddress.c_str());
127 errorMsg = "DNS error.\nCan not reslove " + localAddress;
132 memcpy(&he, phe, sizeof(he));
133 ip = *((long *)he.h_addr_list[0]);
136 struct sockaddr_in localAddr;
137 memset(&localAddr, 0, sizeof(localAddr));
138 localAddr.sin_family = AF_INET;
139 localAddr.sin_port = htons(localPort);
140 localAddr.sin_addr.s_addr = ip;
142 if (bind(sock, (struct sockaddr *)&localAddr, sizeof(localAddr)) < 0)
144 errorMsg = BIND_FAILED;
149 struct sockaddr_in outerAddr;
150 memset(&outerAddr, 0, sizeof(outerAddr));
152 unsigned long ip = inet_addr(server.c_str());
154 if (ip == INADDR_NONE)
156 struct hostent * phe = gethostbyname(server.c_str());
159 errorMsg = "DNS error.\nCan not reslove " + server;
164 memcpy(&he, phe, sizeof(he));
165 ip = *((long *)he.h_addr_list[0]);
168 outerAddr.sin_family = AF_INET;
169 outerAddr.sin_port = htons(port);
170 outerAddr.sin_addr.s_addr = ip;
172 if (connect(sock, (struct sockaddr *)&outerAddr, sizeof(outerAddr)) < 0)
174 errorMsg = CONNECT_FAILED;
180 //---------------------------------------------------------------------------
181 void NETTRANSACT::Disconnect()
185 shutdown(sock, SHUT_RDWR);
190 //---------------------------------------------------------------------------
191 int NETTRANSACT::Transact(const std::string & request, CALLBACK callback, void * data)
194 if ((ret = TxHeader()) != st_ok)
197 if ((ret = RxHeaderAnswer()) != st_ok)
200 if ((ret = TxLogin()) != st_ok)
203 if ((ret = RxLoginAnswer()) != st_ok)
206 if ((ret = TxLoginS()) != st_ok)
209 if ((ret = RxLoginSAnswer()) != st_ok)
212 if ((ret = TxData(request)) != st_ok)
215 if ((ret = RxDataAnswer(callback, data)) != st_ok)
220 //---------------------------------------------------------------------------
221 int NETTRANSACT::TxHeader()
223 if (!WriteAll(sock, STG_HEADER, strlen(STG_HEADER)))
225 errorMsg = SEND_HEADER_ERROR;
231 //---------------------------------------------------------------------------
232 int NETTRANSACT::RxHeaderAnswer()
234 char buffer[sizeof(STG_HEADER) + 1];
236 if (!ReadAll(sock, buffer, strlen(OK_HEADER)))
238 printf("Receive header answer error: '%s'\n", strerror(errno));
239 errorMsg = RECV_HEADER_ANSWER_ERROR;
243 if (strncmp(OK_HEADER, buffer, strlen(OK_HEADER)) == 0)
246 if (strncmp(ERR_HEADER, buffer, strlen(ERR_HEADER)) == 0)
248 errorMsg = INCORRECT_HEADER;
249 return st_header_err;
253 errorMsg = UNKNOWN_ERROR;
254 return st_unknown_err;
257 //---------------------------------------------------------------------------
258 int NETTRANSACT::TxLogin()
260 char loginZ[ADM_LOGIN_LEN + 1];
261 memset(loginZ, 0, ADM_LOGIN_LEN + 1);
262 strncpy(loginZ, login.c_str(), ADM_LOGIN_LEN);
264 if (!WriteAll(sock, loginZ, ADM_LOGIN_LEN))
266 errorMsg = SEND_LOGIN_ERROR;
272 //---------------------------------------------------------------------------
273 int NETTRANSACT::RxLoginAnswer()
275 char buffer[sizeof(OK_LOGIN) + 1];
277 if (!ReadAll(sock, buffer, strlen(OK_LOGIN)))
279 printf("Receive login answer error: '%s'\n", strerror(errno));
280 errorMsg = RECV_LOGIN_ANSWER_ERROR;
284 if (strncmp(OK_LOGIN, buffer, strlen(OK_LOGIN)) == 0)
287 if (strncmp(ERR_LOGIN, buffer, strlen(ERR_LOGIN)) == 0)
289 errorMsg = INCORRECT_LOGIN;
294 errorMsg = UNKNOWN_ERROR;
295 return st_unknown_err;
298 //---------------------------------------------------------------------------
299 int NETTRANSACT::TxLoginS()
301 char loginZ[ADM_LOGIN_LEN + 1];
302 memset(loginZ, 0, ADM_LOGIN_LEN + 1);
305 InitContext(password.c_str(), PASSWD_LEN, &ctx);
306 EncryptString(loginZ, login.c_str(), std::min<size_t>(login.length() + 1, ADM_LOGIN_LEN), &ctx);
307 if (!WriteAll(sock, loginZ, ADM_LOGIN_LEN))
309 errorMsg = SEND_LOGIN_ERROR;
315 //---------------------------------------------------------------------------
316 int NETTRANSACT::RxLoginSAnswer()
318 char buffer[sizeof(OK_LOGINS) + 1];
320 if (!ReadAll(sock, buffer, strlen(OK_LOGINS)))
322 printf("Receive secret login answer error: '%s'\n", strerror(errno));
323 errorMsg = RECV_LOGIN_ANSWER_ERROR;
327 if (strncmp(OK_LOGINS, buffer, strlen(OK_LOGINS)) == 0)
330 if (strncmp(ERR_LOGINS, buffer, strlen(ERR_LOGINS)) == 0)
332 errorMsg = INCORRECT_LOGIN;
333 return st_logins_err;
337 errorMsg = UNKNOWN_ERROR;
338 return st_unknown_err;
341 //---------------------------------------------------------------------------
342 int NETTRANSACT::TxData(const std::string & text)
344 STG::ENCRYPT_STREAM stream(password, TxCrypto, this);
345 stream.Put(text.c_str(), text.length() + 1, true);
348 errorMsg = SEND_DATA_ERROR;
354 //---------------------------------------------------------------------------
355 int NETTRANSACT::RxDataAnswer(CALLBACK callback, void * data)
357 ReadState state = {false, callback, data, this};
358 STG::DECRYPT_STREAM stream(password, RxCrypto, &state);
362 ssize_t res = read(sock, buffer, sizeof(buffer));
365 printf("Receive data error: '%s'\n", strerror(errno));
366 errorMsg = RECV_DATA_ANSWER_ERROR;
369 stream.Put(buffer, res, res == 0);
371 return st_xml_parse_error;
376 //---------------------------------------------------------------------------
377 bool NETTRANSACT::TxCrypto(const void * block, size_t size, void * data)
379 assert(data != NULL);
380 NETTRANSACT & nt = *static_cast<NETTRANSACT *>(data);
381 if (!WriteAll(nt.sock, block, size))
385 //---------------------------------------------------------------------------
386 bool NETTRANSACT::RxCrypto(const void * block, size_t size, void * data)
388 assert(data != NULL);
389 ReadState & state = *static_cast<ReadState *>(data);
391 const char * buffer = static_cast<const char *>(block);
392 for (size_t pos = 0; pos < size; ++pos)
393 if (buffer[pos] == 0)
396 size = pos; // Adjust string size
400 if (!state.callback(std::string(buffer, size), state.final, state.callbackData))