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 1, or (at your option)
 
   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., 675 Mass Ave, Cambridge, MA 02139, USA.
 
  20  $Date: 2010/04/16 11:28:03 $
 
  25 * Boris Mikhailenko <stg34@stargazer.dp.ua>
 
  26 * Maxim Mamontov <faust@stargazer.dp.ua>
 
  27 * Andrey Rakhmanov <andrey_rakhmanov@yahoo.com> - bugfixes.
 
  30 //---------------------------------------------------------------------------
 
  44     #include <sys/types.h>
 
  45     #include <sys/socket.h>
 
  47     #include <netinet/in.h>
 
  48     #include <arpa/inet.h>
 
  53 #include "ia_auth_c.h"
 
  56 #define IA_CONNECT         (1)
 
  57 #define IA_DISCONNECT      (2)
 
  59 #define IA_DEBUGPROTO   1
 
  62 //---------------------------------------------------------------------------
 
  63 //---------------------------------------------------------------------------
 
  64 //---------------------------------------------------------------------------
 
  67 void * RunL(void * data)
 
  70 IA_CLIENT_PROT * c = (IA_CLIENT_PROT *)data;
 
  79 while (c->GetNonstop())
 
  85 //---------------------------------------------------------------------------
 
  90 //---------------------------------------------------------------------------
 
  94 gettimeofday(&tv, NULL);
 
  95 return tv.tv_sec*1000 + tv.tv_usec/1000;
 
  98 //---------------------------------------------------------------------------
 
  99 unsigned long WINAPI RunW(void * data)
 
 101 IA_CLIENT_PROT * c = (IA_CLIENT_PROT *)data;
 
 102 while (c->GetNonstop())
 
 106 //---------------------------------------------------------------------------
 
 108 //---------------------------------------------------------------------------
 
 109 //---------------------------------------------------------------------------
 
 110 //---------------------------------------------------------------------------
 
 111 IA_CLIENT_PROT::IA_CLIENT_PROT(const string & sn, unsigned short p, uint16_t localPort)
 
 117       isNetPrepared(false),
 
 122       localPort(localPort),
 
 130       pStatusChangedCb(NULL),
 
 131       pStatChangedCb(NULL),
 
 135       statusChangedCbData(NULL),
 
 136       statChangedCbData(NULL),
 
 146       disconnSynAck8(NULL),
 
 150 memset(&stat, 0, sizeof(stat));
 
 153 WSAStartup(MAKEWORD(2, 0), &wsaData);
 
 156 packetTypes["CONN_SYN"] = CONN_SYN_N;
 
 157 packetTypes["CONN_SYN_ACK"] = CONN_SYN_ACK_N;
 
 158 packetTypes["CONN_ACK"] = CONN_ACK_N;
 
 159 packetTypes["ALIVE_SYN"] = ALIVE_SYN_N;
 
 160 packetTypes["ALIVE_ACK"] = ALIVE_ACK_N;
 
 161 packetTypes["DISCONN_SYN"] = DISCONN_SYN_N;
 
 162 packetTypes["DISCONN_SYN_ACK"] = DISCONN_SYN_ACK_N;
 
 163 packetTypes["DISCONN_ACK"] = DISCONN_ACK_N;
 
 164 packetTypes["FIN"] = FIN_N;
 
 165 packetTypes["ERR"] = ERROR_N;
 
 166 packetTypes["INFO"] = INFO_N;
 
 167 packetTypes["INFO_7"] = INFO_7_N;
 
 168 packetTypes["INFO_8"] = INFO_8_N;
 
 170 unsigned char key[IA_PASSWD_LEN];
 
 171 memset(key, 0, IA_PASSWD_LEN);
 
 172 strncpy((char *)key, "pr7Hhen", 8);
 
 173 Blowfish_Init(&ctxHdr, key, IA_PASSWD_LEN);
 
 175 memset(key, 0, IA_PASSWD_LEN);
 
 176 Blowfish_Init(&ctxPass, key, IA_PASSWD_LEN);
 
 178 for (size_t i = 0; i < DIR_NUM; ++i)
 
 180     selectedDirs[i] = false;
 
 183 servAddr.sin_family = AF_INET;
 
 184 servAddr.sin_port = htons(port);
 
 185 servAddr.sin_addr.s_addr = ip;
 
 187 //---------------------------------------------------------------------------
 
 188 void IA_CLIENT_PROT::PrepareNet()
 
 190 struct hostent * phe;
 
 193 ip = inet_addr(serverName.c_str());
 
 194 if (ip == INADDR_NONE)
 
 196     phe = gethostbyname(serverName.c_str());
 
 199         ip = *((unsigned long*)phe->h_addr_list[0]);
 
 203         strError = string("Unknown host ") + "\'" + serverName + "\'";
 
 204         codeError = IA_GETHOSTBYNAME_ERROR;
 
 205         if (pErrorCb != NULL)
 
 206             pErrorCb(strError, IA_GETHOSTBYNAME_ERROR, errorCbData);
 
 216 sockr = socket(AF_INET, SOCK_DGRAM, 0);
 
 218 struct sockaddr_in  localAddrR;
 
 219 localAddrR.sin_family = AF_INET;
 
 222     localAddrR.sin_port = htons(localPort);
 
 224     localAddrR.sin_port = htons(port);
 
 225 localAddrR.sin_addr.s_addr = inet_addr("0.0.0.0");
 
 227 servAddr.sin_family = AF_INET;
 
 228 servAddr.sin_port = htons(port);
 
 229 servAddr.sin_addr.s_addr = ip;
 
 231 int res = bind(sockr, (struct sockaddr*)&localAddrR, sizeof(localAddrR));
 
 234     strError = "bind error";
 
 235     codeError = IA_BIND_ERROR;
 
 236     if (pErrorCb != NULL)
 
 237         pErrorCb(strError, IA_BIND_ERROR, errorCbData);
 
 242 unsigned long arg = 1;
 
 243 res = ioctlsocket(sockr, FIONBIO, &arg);
 
 245 if (0 != fcntl(sockr, F_SETFL, O_NONBLOCK))
 
 247     strError = "fcntl error";
 
 248     codeError = IA_FCNTL_ERROR;
 
 249     if (pErrorCb != NULL)
 
 250         pErrorCb(strError, IA_FCNTL_ERROR, errorCbData);
 
 255 //---------------------------------------------------------------------------
 
 256 IA_CLIENT_PROT::~IA_CLIENT_PROT()
 
 265 //---------------------------------------------------------------------------
 
 266 int IA_CLIENT_PROT::DeterminatePacketType(const char * buffer)
 
 268 map<string, int>::iterator pi;
 
 269 pi = packetTypes.find(buffer);
 
 270 if (pi == packetTypes.end())
 
 279 //---------------------------------------------------------------------------
 
 280 void IA_CLIENT_PROT::FillHdr8(char * buffer, unsigned long)
 
 282 strncpy(buffer, IA_ID, 6);
 
 283 buffer[IA_MAGIC_LEN] = 0;
 
 284 buffer[IA_MAGIC_LEN + 1] = IA_PROTO_VER;
 
 285 strncpy(buffer + sizeof(HDR_8), login.c_str(), IA_LOGIN_LEN);
 
 287 //---------------------------------------------------------------------------
 
 288 int IA_CLIENT_PROT::Send(char * buffer, int len)
 
 293     isNetPrepared = true;
 
 296 int db = sizeof(HDR_8);
 
 297 for (int i = 0; i < IA_LOGIN_LEN/8; i++)
 
 299     Blowfish_Encrypt(&ctxHdr, (uint32_t*)(buffer + db + i*8), (uint32_t*)(buffer + db + i*8 + 4));
 
 303 int encLen = (len - sizeof(HDR_8) - IA_LOGIN_LEN)/8;
 
 304 for (int i = 0; i < encLen; i++)
 
 306     Blowfish_Encrypt(&ctxPass, (uint32_t*)(buffer + db), (uint32_t*)(buffer + db + 4));
 
 310 return sendto(sockr, buffer, len, 0, (struct sockaddr*)&servAddr, sizeof(servAddr));
 
 312 //---------------------------------------------------------------------------
 
 313 int IA_CLIENT_PROT::Recv(char * buffer, int len)
 
 321 struct sockaddr_in addr;
 
 322 fromLen = sizeof(addr);
 
 323 int res = recvfrom(sockr, buffer, len, 0, (struct sockaddr*)&addr, &fromLen);
 
 328 if (strcmp(buffer + 4 + sizeof(HDR_8), "ERR"))
 
 330     for (int i = 0; i < len/8; i++)
 
 331         Blowfish_Decrypt(&ctxPass, (uint32_t*)(buffer + i*8), (uint32_t*)(buffer + i*8 + 4));
 
 336 //---------------------------------------------------------------------------
 
 337 int IA_CLIENT_PROT::NetSend(int n)
 
 342 memset(buffer, 0, 2048);
 
 347         msgLen = Prepare_CONN_SYN_8(buffer);
 
 351         msgLen = Prepare_CONN_ACK_8(buffer);
 
 355         msgLen = Prepare_ALIVE_ACK_8(buffer);
 
 359         msgLen = Prepare_DISCONN_SYN_8(buffer);
 
 363         msgLen = Prepare_DISCONN_ACK_8(buffer);
 
 371 Send(buffer, msgLen);
 
 375 //---------------------------------------------------------------------------
 
 376 int IA_CLIENT_PROT::NetRecv()
 
 380 if (Recv(buffer, sizeof(buffer)) < 0)
 
 384 strncpy(packetName, buffer + 12, sizeof(packetName));
 
 385 packetName[sizeof(packetName) - 1] = 0;
 
 386 int pn = DeterminatePacketType(buffer + 12);
 
 392         ret = Process_CONN_SYN_ACK_8(buffer);
 
 396         ret = Process_ALIVE_SYN_8(buffer);
 
 399     case DISCONN_SYN_ACK_N:
 
 400         ret = Process_DISCONN_SYN_ACK_8(buffer);
 
 404         ret = Process_FIN_8(buffer);
 
 408         ret = Process_INFO_8(buffer);
 
 412         ret = Process_ERROR(buffer);
 
 420 //---------------------------------------------------------------------------
 
 421 void IA_CLIENT_PROT::Start()
 
 426 CreateThread(NULL, 16384, RunW, this, 0, &pt);
 
 428 pthread_create(&thread, NULL, RunL, this);
 
 431 //---------------------------------------------------------------------------
 
 432 void IA_CLIENT_PROT::Stop()
 
 436 //---------------------------------------------------------------------------
 
 437 void IA_CLIENT_PROT::Run()
 
 444         if (action == IA_CONNECT)
 
 449             phaseTime = GetTickCount();
 
 451         if (reconnect && !firstConnect)
 
 458         if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout)
 
 461             phaseTime = GetTickCount();
 
 462             if (pStatusChangedCb != NULL)
 
 463                 pStatusChangedCb(0, statusChangedCbData);
 
 466         if (action == IA_DISCONNECT)
 
 469             NetSend(DISCONN_SYN_N);
 
 471             phaseTime = GetTickCount();
 
 477         if ((int)(GetTickCount() - phaseTime)/1000 > userTimeout)
 
 480             phaseTime = GetTickCount();
 
 481             if (pStatusChangedCb != NULL)
 
 482                 pStatusChangedCb(0, statusChangedCbData);
 
 483             firstConnect = false;
 
 486         if (action == IA_DISCONNECT)
 
 489             NetSend(DISCONN_SYN_N);
 
 491             phaseTime = GetTickCount();
 
 497         if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout)
 
 500             phaseTime = GetTickCount();
 
 501             if (pStatusChangedCb != NULL)
 
 502                 pStatusChangedCb(0, statusChangedCbData);
 
 505         if (action == IA_CONNECT)
 
 510             phaseTime = GetTickCount();
 
 516         if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout)
 
 519             phaseTime = GetTickCount();
 
 520             if (pStatusChangedCb != NULL)
 
 521                 pStatusChangedCb(0, statusChangedCbData);
 
 524         if (action == IA_CONNECT)
 
 529             phaseTime = GetTickCount();
 
 537 //---------------------------------------------------------------------------
 
 538 void IA_CLIENT_PROT::GetStat(LOADSTAT * ls)
 
 540 memcpy(ls, &stat, sizeof(stat));
 
 542 //---------------------------------------------------------------------------
 
 543 void IA_CLIENT_PROT::SetServer(const string & sn, unsigned short p)
 
 549 //---------------------------------------------------------------------------
 
 550 void IA_CLIENT_PROT::SetLogin(const string & l)
 
 554 //---------------------------------------------------------------------------
 
 555 void IA_CLIENT_PROT::SetPassword(const string & p)
 
 559 unsigned char keyL[IA_PASSWD_LEN];
 
 560 memset(keyL, 0, IA_PASSWD_LEN);
 
 561 strncpy((char *)keyL, password.c_str(), IA_PASSWD_LEN);
 
 562 Blowfish_Init(&ctxPass, keyL, IA_PASSWD_LEN);
 
 564 //---------------------------------------------------------------------------
 
 565 void IA_CLIENT_PROT::SetEnabledDirs(const bool * selectedDirs)
 
 567 memcpy(IA_CLIENT_PROT::selectedDirs, selectedDirs, sizeof(bool) * DIR_NUM);
 
 569 //---------------------------------------------------------------------------
 
 570 int IA_CLIENT_PROT::Connect()
 
 575 //---------------------------------------------------------------------------
 
 576 int IA_CLIENT_PROT::Disconnect()
 
 579 action = IA_DISCONNECT;
 
 582 //---------------------------------------------------------------------------
 
 583 int IA_CLIENT_PROT::GetStrError(string * error) const
 
 591 //---------------------------------------------------------------------------
 
 592 int IA_CLIENT_PROT::Process_CONN_SYN_ACK_8(const char * buffer)
 
 594 vector<string> dirNames;
 
 595 connSynAck8 = (CONN_SYN_ACK_8*)buffer;
 
 598 SwapBytes(connSynAck8->len);
 
 599 SwapBytes(connSynAck8->rnd);
 
 600 SwapBytes(connSynAck8->userTimeOut);
 
 601 SwapBytes(connSynAck8->aliveDelay);
 
 604 rnd = connSynAck8->rnd;
 
 605 userTimeout = connSynAck8->userTimeOut;
 
 606 aliveTimeout = connSynAck8->aliveDelay;
 
 608 for (int i = 0; i < DIR_NUM; i++)
 
 610     dirNames.push_back((const char*)connSynAck8->dirName[i]);
 
 613 if (pDirNameCb != NULL)
 
 614     pDirNameCb(dirNames, dirNameCbData);
 
 618 phaseTime = GetTickCount();
 
 620 return CONN_SYN_ACK_N;
 
 622 //---------------------------------------------------------------------------
 
 623 int IA_CLIENT_PROT::Process_ALIVE_SYN_8(const char * buffer)
 
 625 aliveSyn8 = (ALIVE_SYN_8*)buffer;
 
 628 SwapBytes(aliveSyn8->len);
 
 629 SwapBytes(aliveSyn8->rnd);
 
 630 SwapBytes(aliveSyn8->cash);
 
 631 SwapBytes(aliveSyn8->status);
 
 632 for (int i = 0; i < DIR_NUM; ++i)
 
 634     SwapBytes(aliveSyn8->mu[i]);
 
 635     SwapBytes(aliveSyn8->md[i]);
 
 636     SwapBytes(aliveSyn8->su[i]);
 
 637     SwapBytes(aliveSyn8->sd[i]);
 
 641 rnd = aliveSyn8->rnd;
 
 642 memcpy(&stat, (char*)aliveSyn8->mu, sizeof(stat));
 
 644 if (pStatChangedCb != NULL)
 
 645     pStatChangedCb(stat, statChangedCbData);
 
 647 if (pStatusChangedCb != NULL)
 
 648     pStatusChangedCb(1, statusChangedCbData);
 
 649 NetSend(ALIVE_ACK_N);
 
 650 phaseTime = GetTickCount();
 
 654 //---------------------------------------------------------------------------
 
 655 int IA_CLIENT_PROT::Process_DISCONN_SYN_ACK_8(const char * buffer)
 
 657 disconnSynAck8 = (DISCONN_SYN_ACK_8*)buffer;
 
 660 SwapBytes(disconnSynAck8->len);
 
 661 SwapBytes(disconnSynAck8->rnd);
 
 664 rnd = disconnSynAck8->rnd;
 
 666 NetSend(DISCONN_ACK_N);
 
 668 phaseTime = GetTickCount();
 
 670 return DISCONN_SYN_ACK_N;
 
 672 //---------------------------------------------------------------------------
 
 673 int IA_CLIENT_PROT::Process_FIN_8(const char *)
 
 676 phaseTime = GetTickCount();
 
 677 if (pStatusChangedCb != NULL)
 
 678     pStatusChangedCb(0, statusChangedCbData);
 
 682 //---------------------------------------------------------------------------
 
 683 int IA_CLIENT_PROT::Process_INFO_8(const char * buffer)
 
 685 info = (INFO_8*)buffer;
 
 688 SwapBytes(info->len);
 
 689 SwapBytes(info->sendTime);
 
 693     pInfoCb((char*)info->text, info->infoType, info->showTime, info->sendTime, infoCbData);
 
 696 //---------------------------------------------------------------------------
 
 697 int IA_CLIENT_PROT::Process_ERROR(const char * buffer)
 
 700 memcpy(&err, buffer, sizeof(err));
 
 706 KOIToWin((const char*)err.text, &messageText);
 
 707 if (pErrorCb != NULL)
 
 708     pErrorCb(messageText, IA_SERVER_ERROR, errorCbData);
 
 710 phaseTime = GetTickCount();
 
 711 codeError = IA_SERVER_ERROR;
 
 715 //---------------------------------------------------------------------------
 
 716 int IA_CLIENT_PROT::Prepare_CONN_SYN_8(char * buffer)
 
 718 connSyn8 = (CONN_SYN_8*)buffer;
 
 721 SwapBytes(connSyn8->len);
 
 724 assert(sizeof(CONN_SYN_8) == Min8(sizeof(CONN_SYN_8)) && "CONN_SYN_8 is not aligned to 8 bytes");
 
 726 connSyn8->len = sizeof(CONN_SYN_8);
 
 727 strncpy((char*)connSyn8->type, "CONN_SYN", IA_MAX_TYPE_LEN);
 
 728 strncpy((char*)connSyn8->login, login.c_str(), IA_LOGIN_LEN);
 
 730 for (int i = 0; i < DIR_NUM; i++)
 
 732     connSyn8->dirs |= (selectedDirs[i] << i);
 
 734 return connSyn8->len;
 
 736 //---------------------------------------------------------------------------
 
 737 int IA_CLIENT_PROT::Prepare_CONN_ACK_8(char * buffer)
 
 739 connAck8 = (CONN_ACK_8*)buffer;
 
 742 SwapBytes(connAck8->len);
 
 743 SwapBytes(connAck8->rnd);
 
 746 assert(sizeof(CONN_ACK_8) == Min8(sizeof(CONN_ACK_8)) && "CONN_ACK_8 is not aligned to 8 bytes");
 
 748 connAck8->len = sizeof(CONN_ACK_8);
 
 749 strncpy((char*)connAck8->loginS, login.c_str(), IA_LOGIN_LEN);
 
 750 strncpy((char*)connAck8->type, "CONN_ACK", IA_MAX_TYPE_LEN);
 
 754 return connAck8->len;
 
 756 //---------------------------------------------------------------------------
 
 757 int IA_CLIENT_PROT::Prepare_ALIVE_ACK_8(char * buffer)
 
 759 aliveAck8 = (ALIVE_ACK_8*)buffer;
 
 762 SwapBytes(aliveAck8->len);
 
 763 SwapBytes(aliveAck8->rnd);
 
 766 assert(Min8(sizeof(ALIVE_ACK_8)) == sizeof(ALIVE_ACK_8) && "ALIVE_ACK_8 is not aligned to 8 bytes");
 
 768 aliveAck8 = (ALIVE_ACK_8*)buffer;
 
 769 aliveAck8->len = sizeof(ALIVE_ACK_8);
 
 770 strncpy((char*)aliveAck8->loginS, login.c_str(), IA_LOGIN_LEN);
 
 771 strncpy((char*)aliveAck8->type, "ALIVE_ACK", IA_MAX_TYPE_LEN);
 
 772 aliveAck8->rnd = ++rnd;
 
 773 return aliveAck8->len;
 
 775 //---------------------------------------------------------------------------
 
 776 int IA_CLIENT_PROT::Prepare_DISCONN_SYN_8(char * buffer)
 
 778 disconnSyn8 = (DISCONN_SYN_8*)buffer;
 
 781 SwapBytes(disconnSyn8->len);
 
 784 assert(Min8(sizeof(DISCONN_SYN_8)) == sizeof(DISCONN_SYN_8) && "DISCONN_SYN_8 is not aligned to 8 bytes");
 
 786 disconnSyn8->len = sizeof(DISCONN_SYN_8);
 
 787 strncpy((char*)disconnSyn8->loginS, login.c_str(), IA_LOGIN_LEN);
 
 788 strncpy((char*)disconnSyn8->type, "DISCONN_SYN", IA_MAX_TYPE_LEN);
 
 789 strncpy((char*)disconnSyn8->login, login.c_str(), IA_LOGIN_LEN);
 
 790 return disconnSyn8->len;
 
 792 //---------------------------------------------------------------------------
 
 793 int IA_CLIENT_PROT::Prepare_DISCONN_ACK_8(char * buffer)
 
 795 disconnAck8 = (DISCONN_ACK_8*)buffer;
 
 798 SwapBytes(disconnAck8->len);
 
 799 SwapBytes(disconnAck8->rnd);
 
 802 assert(Min8(sizeof(DISCONN_ACK_8)) == sizeof(DISCONN_ACK_8) && "DISCONN_ACK_8 is not aligned to 8 bytes");
 
 804 disconnAck8->len = Min8(sizeof(DISCONN_ACK_8));
 
 805 disconnAck8->rnd = rnd + 1;
 
 806 strncpy((char*)disconnAck8->loginS, login.c_str(), IA_LOGIN_LEN);
 
 807 strncpy((char*)disconnAck8->type, "DISCONN_ACK", IA_MAX_TYPE_LEN);
 
 808 return disconnAck8->len;
 
 810 //---------------------------------------------------------------------------
 
 811 void IA_CLIENT_PROT::SetStatusChangedCb(tpStatusChangedCb p, void * data)
 
 813 pStatusChangedCb = p;
 
 814 statusChangedCbData = data;
 
 816 //---------------------------------------------------------------------------
 
 817 void IA_CLIENT_PROT::SetStatChangedCb(tpStatChangedCb p, void * data)
 
 820 statChangedCbData = data;
 
 822 //---------------------------------------------------------------------------
 
 823 void IA_CLIENT_PROT::SetInfoCb(tpCallBackInfoFn p, void * data)
 
 828 //---------------------------------------------------------------------------
 
 829 void IA_CLIENT_PROT::SetDirNameCb(tpCallBackDirNameFn p, void * data)
 
 832 dirNameCbData = data;
 
 834 //---------------------------------------------------------------------------
 
 835 void IA_CLIENT_PROT::SetErrorCb(tpCallBackErrorFn p, void * data)
 
 840 //---------------------------------------------------------------------------