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>
 
  51     NETTRANSACT::CALLBACK callback;
 
  58 //---------------------------------------------------------------------------
 
  60 #define SEND_DATA_ERROR             "Send data error!"
 
  61 #define RECV_DATA_ANSWER_ERROR      "Recv data answer error!"
 
  62 #define UNKNOWN_ERROR               "Unknown error!"
 
  63 #define CONNECT_FAILED              "Connect failed!"
 
  64 #define BIND_FAILED                 "Bind failed!"
 
  65 #define INCORRECT_LOGIN             "Incorrect login!"
 
  66 #define INCORRECT_HEADER            "Incorrect header!"
 
  67 #define SEND_LOGIN_ERROR            "Send login error!"
 
  68 #define RECV_LOGIN_ANSWER_ERROR     "Recv login answer error!"
 
  69 #define CREATE_SOCKET_ERROR         "Create socket failed!"
 
  70 #define WSASTARTUP_FAILED           "WSAStartup failed!"
 
  71 #define SEND_HEADER_ERROR           "Send header error!"
 
  72 #define RECV_HEADER_ANSWER_ERROR    "Recv header answer error!"
 
  74 //---------------------------------------------------------------------------
 
  75 NETTRANSACT::NETTRANSACT(const std::string & s, uint16_t p,
 
  76                          const std::string & l, const std::string & pwd)
 
  85 //---------------------------------------------------------------------------
 
  86 NETTRANSACT::NETTRANSACT(const std::string & s, uint16_t p,
 
  87                          const std::string & la, uint16_t lp,
 
  88                          const std::string & l, const std::string & pwd)
 
  98 //---------------------------------------------------------------------------
 
  99 NETTRANSACT::~NETTRANSACT()
 
 103 //---------------------------------------------------------------------------
 
 104 int NETTRANSACT::Connect()
 
 106 sock = socket(PF_INET, SOCK_STREAM, 0);
 
 109     errorMsg = CREATE_SOCKET_ERROR;
 
 113 if (!localAddress.empty())
 
 118     unsigned long ip = inet_addr(localAddress.c_str());
 
 120     if (ip == INADDR_NONE)
 
 122         struct hostent * phe = gethostbyname(localAddress.c_str());
 
 125             errorMsg = "Can not reslove '" + localAddress + "'";
 
 130         memcpy(&he, phe, sizeof(he));
 
 131         ip = *((long *)he.h_addr_list[0]);
 
 134     struct sockaddr_in localAddr;
 
 135     memset(&localAddr, 0, sizeof(localAddr));
 
 136     localAddr.sin_family = AF_INET;
 
 137     localAddr.sin_port = htons(localPort);
 
 138     localAddr.sin_addr.s_addr = ip;
 
 140     if (bind(sock, (struct sockaddr *)&localAddr, sizeof(localAddr)) < 0)
 
 142         errorMsg = BIND_FAILED;
 
 147 struct sockaddr_in outerAddr;
 
 148 memset(&outerAddr, 0, sizeof(outerAddr));
 
 150 unsigned long ip = inet_addr(server.c_str());
 
 152 if (ip == INADDR_NONE)
 
 154     struct hostent * phe = gethostbyname(server.c_str());
 
 157         errorMsg = "Can not reslove '" + server + "'";
 
 162     memcpy(&he, phe, sizeof(he));
 
 163     ip = *((long *)he.h_addr_list[0]);
 
 166 outerAddr.sin_family = AF_INET;
 
 167 outerAddr.sin_port = htons(port);
 
 168 outerAddr.sin_addr.s_addr = ip;
 
 170 if (connect(sock, (struct sockaddr *)&outerAddr, sizeof(outerAddr)) < 0)
 
 172     errorMsg = CONNECT_FAILED;
 
 178 //---------------------------------------------------------------------------
 
 179 void NETTRANSACT::Disconnect()
 
 183     shutdown(sock, SHUT_RDWR);
 
 188 //---------------------------------------------------------------------------
 
 189 int NETTRANSACT::Transact(const std::string & request, CALLBACK callback, void * data)
 
 192 if ((ret = TxHeader()) != st_ok)
 
 195 if ((ret = RxHeaderAnswer()) != st_ok)
 
 198 if ((ret = TxLogin()) != st_ok)
 
 201 if ((ret = RxLoginAnswer()) != st_ok)
 
 204 if ((ret = TxLoginS()) != st_ok)
 
 207 if ((ret = RxLoginSAnswer()) != st_ok)
 
 210 if ((ret = TxData(request)) != st_ok)
 
 213 if ((ret = RxDataAnswer(callback, data)) != st_ok)
 
 218 //---------------------------------------------------------------------------
 
 219 int NETTRANSACT::TxHeader()
 
 221 if (!WriteAll(sock, STG_HEADER, strlen(STG_HEADER)))
 
 223     errorMsg = SEND_HEADER_ERROR;
 
 229 //---------------------------------------------------------------------------
 
 230 int NETTRANSACT::RxHeaderAnswer()
 
 232 char buffer[sizeof(STG_HEADER) + 1];
 
 234 if (!ReadAll(sock, buffer, strlen(OK_HEADER)))
 
 236     printf("Receive header answer error: '%s'\n", strerror(errno));
 
 237     errorMsg = RECV_HEADER_ANSWER_ERROR;
 
 241 if (strncmp(OK_HEADER, buffer, strlen(OK_HEADER)) == 0)
 
 244 if (strncmp(ERR_HEADER, buffer, strlen(ERR_HEADER)) == 0)
 
 246     errorMsg = INCORRECT_HEADER;
 
 247     return st_header_err;
 
 251     errorMsg = UNKNOWN_ERROR;
 
 252     return st_unknown_err;
 
 255 //---------------------------------------------------------------------------
 
 256 int NETTRANSACT::TxLogin()
 
 258 char loginZ[ADM_LOGIN_LEN + 1];
 
 259 memset(loginZ, 0, ADM_LOGIN_LEN + 1);
 
 260 strncpy(loginZ, login.c_str(), ADM_LOGIN_LEN);
 
 262 if (!WriteAll(sock, loginZ, ADM_LOGIN_LEN))
 
 264     errorMsg = SEND_LOGIN_ERROR;
 
 270 //---------------------------------------------------------------------------
 
 271 int NETTRANSACT::RxLoginAnswer()
 
 273 char buffer[sizeof(OK_LOGIN) + 1];
 
 275 if (!ReadAll(sock, buffer, strlen(OK_LOGIN)))
 
 277     printf("Receive login answer error: '%s'\n", strerror(errno));
 
 278     errorMsg = RECV_LOGIN_ANSWER_ERROR;
 
 282 if (strncmp(OK_LOGIN, buffer, strlen(OK_LOGIN)) == 0)
 
 285 if (strncmp(ERR_LOGIN, buffer, strlen(ERR_LOGIN)) == 0)
 
 287     errorMsg = INCORRECT_LOGIN;
 
 292     errorMsg = UNKNOWN_ERROR;
 
 293     return st_unknown_err;
 
 296 //---------------------------------------------------------------------------
 
 297 int NETTRANSACT::TxLoginS()
 
 299 char loginZ[ADM_LOGIN_LEN + 1];
 
 300 memset(loginZ, 0, ADM_LOGIN_LEN + 1);
 
 303 InitContext(password.c_str(), PASSWD_LEN, &ctx);
 
 304 EncryptString(loginZ, login.c_str(), std::min<size_t>(login.length() + 1, ADM_LOGIN_LEN), &ctx);
 
 305 if (!WriteAll(sock, loginZ, ADM_LOGIN_LEN))
 
 307     errorMsg = SEND_LOGIN_ERROR;
 
 313 //---------------------------------------------------------------------------
 
 314 int NETTRANSACT::RxLoginSAnswer()
 
 316 char buffer[sizeof(OK_LOGINS) + 1];
 
 318 if (!ReadAll(sock, buffer, strlen(OK_LOGINS)))
 
 320     printf("Receive secret login answer error: '%s'\n", strerror(errno));
 
 321     errorMsg = RECV_LOGIN_ANSWER_ERROR;
 
 325 if (strncmp(OK_LOGINS, buffer, strlen(OK_LOGINS)) == 0)
 
 328 if (strncmp(ERR_LOGINS, buffer, strlen(ERR_LOGINS)) == 0)
 
 330     errorMsg = INCORRECT_LOGIN;
 
 331     return st_logins_err;
 
 335     errorMsg = UNKNOWN_ERROR;
 
 336     return st_unknown_err;
 
 339 //---------------------------------------------------------------------------
 
 340 int NETTRANSACT::TxData(const std::string & text)
 
 342 STG::ENCRYPT_STREAM stream(password, TxCrypto, this);
 
 343 stream.Put(text.c_str(), text.length() + 1, true);
 
 346     errorMsg = SEND_DATA_ERROR;
 
 352 //---------------------------------------------------------------------------
 
 353 int NETTRANSACT::RxDataAnswer(CALLBACK callback, void * data)
 
 355 ReadState state = {false, callback, data, this};
 
 356 STG::DECRYPT_STREAM stream(password, RxCrypto, &state);
 
 360     ssize_t res = read(sock, buffer, sizeof(buffer));
 
 363         printf("Receive data error: '%s'\n", strerror(errno));
 
 364         errorMsg = RECV_DATA_ANSWER_ERROR;
 
 367     stream.Put(buffer, res, res == 0);
 
 369         return st_xml_parse_error;
 
 374 //---------------------------------------------------------------------------
 
 375 bool NETTRANSACT::TxCrypto(const void * block, size_t size, void * data)
 
 377 assert(data != NULL);
 
 378 NETTRANSACT & nt = *static_cast<NETTRANSACT *>(data);
 
 379 if (!WriteAll(nt.sock, block, size))
 
 383 //---------------------------------------------------------------------------
 
 384 bool NETTRANSACT::RxCrypto(const void * block, size_t size, void * data)
 
 386 assert(data != NULL);
 
 387 ReadState & state = *static_cast<ReadState *>(data);
 
 389 const char * buffer = static_cast<const char *>(block);
 
 390 for (size_t pos = 0; pos < size; ++pos)
 
 391     if (buffer[pos] == 0)
 
 394         size = pos; // Adjust string size
 
 398     if (!state.callback(std::string(buffer, size), state.final, state.callbackData))