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 //---------------------------------------------------------------------------
40 #include <arpa/inet.h>
50 #include "stg/common.h"
54 #define IA_CONNECT (1)
55 #define IA_DISCONNECT (2)
57 #define IA_DEBUGPROTO 1
60 //---------------------------------------------------------------------------
61 //---------------------------------------------------------------------------
62 //---------------------------------------------------------------------------
67 long long res = ms * 1000000;
68 struct timespec ts = {res / 1000000000, res % 1000000000};
71 //---------------------------------------------------------------------------
72 void * RunL(void * data)
75 sigfillset(&signalSet);
76 pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
78 IA_CLIENT_PROT * c = (IA_CLIENT_PROT *)data;
87 while (c->GetNonstop())
93 //---------------------------------------------------------------------------
97 gettimeofday(&tv, NULL);
98 return tv.tv_sec*1000 + tv.tv_usec/1000;
101 //---------------------------------------------------------------------------
102 unsigned long WINAPI RunW(void * data)
104 IA_CLIENT_PROT * c = (IA_CLIENT_PROT *)data;
105 while (c->GetNonstop())
109 //---------------------------------------------------------------------------
115 bool HostNameToIP(const std::string & hostName, uint32_t & ip)
117 ip = inet_addr(hostName.c_str());
118 if (ip == INADDR_NONE)
120 hostent * phe = gethostbyname(hostName.c_str());
123 ip = *((uint32_t *)phe->h_addr_list[0]);
136 //---------------------------------------------------------------------------
137 //---------------------------------------------------------------------------
138 //---------------------------------------------------------------------------
139 IA_CLIENT_PROT::IA_CLIENT_PROT(const std::string & sn, unsigned short p,
140 const std::string & ln, uint16_t lp)
146 isNetPrepared(false),
160 pStatusChangedCb(NULL),
161 pStatChangedCb(NULL),
165 statusChangedCbData(NULL),
166 statChangedCbData(NULL),
176 disconnSynAck8(NULL),
180 memset(&stat, 0, sizeof(stat));
183 WSAStartup(MAKEWORD(2, 0), &wsaData);
186 packetTypes["CONN_SYN"] = CONN_SYN_N;
187 packetTypes["CONN_SYN_ACK"] = CONN_SYN_ACK_N;
188 packetTypes["CONN_ACK"] = CONN_ACK_N;
189 packetTypes["ALIVE_SYN"] = ALIVE_SYN_N;
190 packetTypes["ALIVE_ACK"] = ALIVE_ACK_N;
191 packetTypes["DISCONN_SYN"] = DISCONN_SYN_N;
192 packetTypes["DISCONN_SYN_ACK"] = DISCONN_SYN_ACK_N;
193 packetTypes["DISCONN_ACK"] = DISCONN_ACK_N;
194 packetTypes["FIN"] = FIN_N;
195 packetTypes["ERR"] = ERROR_N;
196 packetTypes["INFO"] = INFO_N;
197 packetTypes["INFO_7"] = INFO_7_N;
198 packetTypes["INFO_8"] = INFO_8_N;
200 unsigned char key[IA_PASSWD_LEN];
201 memset(key, 0, IA_PASSWD_LEN);
202 strncpy((char *)key, "pr7Hhen", 8);
203 Blowfish_Init(&ctxHdr, key, IA_PASSWD_LEN);
205 memset(key, 0, IA_PASSWD_LEN);
206 Blowfish_Init(&ctxPass, key, IA_PASSWD_LEN);
208 for (size_t i = 0; i < DIR_NUM; ++i)
210 selectedDirs[i] = false;
213 servAddr.sin_family = AF_INET;
214 servAddr.sin_port = htons(port);
215 servAddr.sin_addr.s_addr = ip;
217 //---------------------------------------------------------------------------
218 void IA_CLIENT_PROT::PrepareNet()
220 /*struct hostent * phe;
223 ip = inet_addr(serverName.c_str());
224 if (ip == INADDR_NONE)
226 phe = gethostbyname(serverName.c_str());
229 ip = *((unsigned long*)phe->h_addr_list[0]);
233 strError = string("Unknown host ") + "\'" + serverName + "\'";
234 codeError = IA_GETHOSTBYNAME_ERROR;
235 if (pErrorCb != NULL)
236 pErrorCb(strError, IA_GETHOSTBYNAME_ERROR, errorCbData);
240 if (!HostNameToIP(serverName, ip))
243 strError = std::string("Unknown host ") + "\'" + serverName + "\'";
244 codeError = IA_GETHOSTBYNAME_ERROR;
245 if (pErrorCb != NULL)
246 pErrorCb(strError, IA_GETHOSTBYNAME_ERROR, errorCbData);
256 sockr = socket(AF_INET, SOCK_DGRAM, 0);
258 struct sockaddr_in localAddrR;
259 localAddrR.sin_family = AF_INET;
262 localAddrR.sin_port = htons(localPort);
264 localAddrR.sin_port = htons(port);
266 if (!localName.empty())
268 if (!HostNameToIP(localName, localIP))
270 strError = std::string("Unknown host ") + "\'" + serverName + "\'";
271 codeError = IA_GETHOSTBYNAME_ERROR;
272 if (pErrorCb != NULL)
273 pErrorCb(strError, IA_GETHOSTBYNAME_ERROR, errorCbData);
274 localIP = INADDR_ANY;
279 localIP = INADDR_ANY;
282 localAddrR.sin_addr.s_addr = localIP;
284 servAddr.sin_family = AF_INET;
285 servAddr.sin_port = htons(port);
286 servAddr.sin_addr.s_addr = ip;
288 int res = bind(sockr, (struct sockaddr*)&localAddrR, sizeof(localAddrR));
291 strError = "bind error";
292 codeError = IA_BIND_ERROR;
293 if (pErrorCb != NULL)
294 pErrorCb(strError, IA_BIND_ERROR, errorCbData);
299 unsigned long arg = 1;
300 res = ioctlsocket(sockr, FIONBIO, &arg);
302 if (0 != fcntl(sockr, F_SETFL, O_NONBLOCK))
304 strError = "fcntl error";
305 codeError = IA_FCNTL_ERROR;
306 if (pErrorCb != NULL)
307 pErrorCb(strError, IA_FCNTL_ERROR, errorCbData);
312 //---------------------------------------------------------------------------
313 IA_CLIENT_PROT::~IA_CLIENT_PROT()
322 //---------------------------------------------------------------------------
323 int IA_CLIENT_PROT::DeterminatePacketType(const char * buffer)
325 std::map<std::string, int>::iterator pi;
326 pi = packetTypes.find(buffer);
327 if (pi == packetTypes.end())
336 //---------------------------------------------------------------------------
337 void IA_CLIENT_PROT::FillHdr8(char * buffer, unsigned long)
339 strncpy(buffer, IA_ID, 6);
340 buffer[IA_MAGIC_LEN] = 0;
341 buffer[IA_MAGIC_LEN + 1] = IA_PROTO_VER;
342 strncpy(buffer + sizeof(HDR_8), login.c_str(), IA_LOGIN_LEN);
344 //---------------------------------------------------------------------------
345 int IA_CLIENT_PROT::Send(char * buffer, int len)
350 isNetPrepared = true;
353 int db = sizeof(HDR_8);
354 for (int i = 0; i < IA_LOGIN_LEN/8; i++)
356 EncodeString(buffer + db + i * 8, buffer + db + i * 8, &ctxHdr);
360 int encLen = (len - sizeof(HDR_8) - IA_LOGIN_LEN)/8;
361 for (int i = 0; i < encLen; i++)
363 EncodeString(buffer + db, buffer + db, &ctxPass);
367 return sendto(sockr, buffer, len, 0, (struct sockaddr*)&servAddr, sizeof(servAddr));
369 //---------------------------------------------------------------------------
370 int IA_CLIENT_PROT::Recv(char * buffer, int len)
378 struct sockaddr_in addr;
379 fromLen = sizeof(addr);
380 int res = recvfrom(sockr, buffer, len, 0, (struct sockaddr*)&addr, &fromLen);
385 if (strcmp(buffer + 4 + sizeof(HDR_8), "ERR"))
387 for (int i = 0; i < len / 8; i++)
388 DecodeString(buffer + i * 8, buffer + i * 8, &ctxPass);
393 //---------------------------------------------------------------------------
394 int IA_CLIENT_PROT::NetSend(int n)
399 memset(buffer, 0, 2048);
404 msgLen = Prepare_CONN_SYN_8(buffer);
408 msgLen = Prepare_CONN_ACK_8(buffer);
412 msgLen = Prepare_ALIVE_ACK_8(buffer);
416 msgLen = Prepare_DISCONN_SYN_8(buffer);
420 msgLen = Prepare_DISCONN_ACK_8(buffer);
428 Send(buffer, msgLen);
432 //---------------------------------------------------------------------------
433 int IA_CLIENT_PROT::NetRecv()
437 if (Recv(buffer, sizeof(buffer)) < 0)
441 strncpy(packetName, buffer + 12, sizeof(packetName));
442 packetName[sizeof(packetName) - 1] = 0;
443 int pn = DeterminatePacketType(buffer + 12);
449 ret = Process_CONN_SYN_ACK_8(buffer);
453 ret = Process_ALIVE_SYN_8(buffer);
456 case DISCONN_SYN_ACK_N:
457 ret = Process_DISCONN_SYN_ACK_8(buffer);
461 ret = Process_FIN_8(buffer);
465 ret = Process_INFO_8(buffer);
469 ret = Process_ERROR(buffer);
477 //---------------------------------------------------------------------------
478 void IA_CLIENT_PROT::Start()
483 CreateThread(NULL, 16384, RunW, this, 0, &pt);
485 pthread_create(&thread, NULL, RunL, this);
488 //---------------------------------------------------------------------------
489 void IA_CLIENT_PROT::Stop()
493 //---------------------------------------------------------------------------
494 void IA_CLIENT_PROT::Run()
501 if (action == IA_CONNECT)
506 phaseTime = GetTickCount();
508 if (reconnect && !firstConnect)
515 if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout)
518 phaseTime = GetTickCount();
519 if (pStatusChangedCb != NULL)
520 pStatusChangedCb(0, statusChangedCbData);
523 if (action == IA_DISCONNECT)
526 NetSend(DISCONN_SYN_N);
528 phaseTime = GetTickCount();
534 if ((int)(GetTickCount() - phaseTime)/1000 > userTimeout)
537 phaseTime = GetTickCount();
538 if (pStatusChangedCb != NULL)
539 pStatusChangedCb(0, statusChangedCbData);
540 firstConnect = false;
543 if (action == IA_DISCONNECT)
546 NetSend(DISCONN_SYN_N);
548 phaseTime = GetTickCount();
554 if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout)
557 phaseTime = GetTickCount();
558 if (pStatusChangedCb != NULL)
559 pStatusChangedCb(0, statusChangedCbData);
562 if (action == IA_CONNECT)
567 phaseTime = GetTickCount();
573 if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout)
576 phaseTime = GetTickCount();
577 if (pStatusChangedCb != NULL)
578 pStatusChangedCb(0, statusChangedCbData);
581 if (action == IA_CONNECT)
586 phaseTime = GetTickCount();
594 //---------------------------------------------------------------------------
595 void IA_CLIENT_PROT::GetStat(LOADSTAT * ls)
597 memcpy(ls, &stat, sizeof(stat));
599 //---------------------------------------------------------------------------
600 void IA_CLIENT_PROT::SetServer(const std::string & sn, unsigned short p)
606 //---------------------------------------------------------------------------
607 void IA_CLIENT_PROT::SetLogin(const std::string & l)
611 //---------------------------------------------------------------------------
612 void IA_CLIENT_PROT::SetPassword(const std::string & p)
616 unsigned char keyL[IA_PASSWD_LEN];
617 memset(keyL, 0, IA_PASSWD_LEN);
618 strncpy((char *)keyL, password.c_str(), IA_PASSWD_LEN);
619 Blowfish_Init(&ctxPass, keyL, IA_PASSWD_LEN);
621 //---------------------------------------------------------------------------
622 void IA_CLIENT_PROT::SetEnabledDirs(const bool * selectedDirs)
624 memcpy(IA_CLIENT_PROT::selectedDirs, selectedDirs, sizeof(bool) * DIR_NUM);
626 //---------------------------------------------------------------------------
627 int IA_CLIENT_PROT::Connect()
632 //---------------------------------------------------------------------------
633 int IA_CLIENT_PROT::Disconnect()
636 action = IA_DISCONNECT;
639 //---------------------------------------------------------------------------
640 int IA_CLIENT_PROT::GetStrError(std::string * error) const
648 //---------------------------------------------------------------------------
649 int IA_CLIENT_PROT::Process_CONN_SYN_ACK_8(const char * buffer)
651 std::vector<std::string> dirNames;
652 connSynAck8 = (CONN_SYN_ACK_8*)buffer;
655 SwapBytes(connSynAck8->len);
656 SwapBytes(connSynAck8->rnd);
657 SwapBytes(connSynAck8->userTimeOut);
658 SwapBytes(connSynAck8->aliveDelay);
661 rnd = connSynAck8->rnd;
662 userTimeout = connSynAck8->userTimeOut;
663 aliveTimeout = connSynAck8->aliveDelay;
665 for (int i = 0; i < DIR_NUM; i++)
667 dirNames.push_back((const char*)connSynAck8->dirName[i]);
670 if (pDirNameCb != NULL)
671 pDirNameCb(dirNames, dirNameCbData);
675 phaseTime = GetTickCount();
677 return CONN_SYN_ACK_N;
679 //---------------------------------------------------------------------------
680 int IA_CLIENT_PROT::Process_ALIVE_SYN_8(const char * buffer)
682 aliveSyn8 = (ALIVE_SYN_8*)buffer;
685 SwapBytes(aliveSyn8->len);
686 SwapBytes(aliveSyn8->rnd);
687 SwapBytes(aliveSyn8->cash);
688 SwapBytes(aliveSyn8->status);
689 for (int i = 0; i < DIR_NUM; ++i)
691 SwapBytes(aliveSyn8->mu[i]);
692 SwapBytes(aliveSyn8->md[i]);
693 SwapBytes(aliveSyn8->su[i]);
694 SwapBytes(aliveSyn8->sd[i]);
698 rnd = aliveSyn8->rnd;
699 memcpy(&stat, (char*)aliveSyn8->mu, sizeof(stat));
701 if (pStatChangedCb != NULL)
702 pStatChangedCb(stat, statChangedCbData);
704 if (pStatusChangedCb != NULL)
705 pStatusChangedCb(1, statusChangedCbData);
706 NetSend(ALIVE_ACK_N);
707 phaseTime = GetTickCount();
711 //---------------------------------------------------------------------------
712 int IA_CLIENT_PROT::Process_DISCONN_SYN_ACK_8(const char * buffer)
714 disconnSynAck8 = (DISCONN_SYN_ACK_8*)buffer;
717 SwapBytes(disconnSynAck8->len);
718 SwapBytes(disconnSynAck8->rnd);
721 rnd = disconnSynAck8->rnd;
723 NetSend(DISCONN_ACK_N);
725 phaseTime = GetTickCount();
727 return DISCONN_SYN_ACK_N;
729 //---------------------------------------------------------------------------
730 int IA_CLIENT_PROT::Process_FIN_8(const char *)
733 phaseTime = GetTickCount();
734 if (pStatusChangedCb != NULL)
735 pStatusChangedCb(0, statusChangedCbData);
739 //---------------------------------------------------------------------------
740 int IA_CLIENT_PROT::Process_INFO_8(const char * buffer)
742 info = (INFO_8*)buffer;
745 SwapBytes(info->len);
746 SwapBytes(info->sendTime);
750 pInfoCb((char*)info->text, info->infoType, info->showTime, info->sendTime, infoCbData);
753 //---------------------------------------------------------------------------
754 int IA_CLIENT_PROT::Process_ERROR(const char * buffer)
757 memcpy(&err, buffer, sizeof(err));
763 KOIToWin((const char*)err.text, &messageText);
764 if (pErrorCb != NULL)
765 pErrorCb(messageText, IA_SERVER_ERROR, errorCbData);
767 phaseTime = GetTickCount();
768 codeError = IA_SERVER_ERROR;
772 //---------------------------------------------------------------------------
773 int IA_CLIENT_PROT::Prepare_CONN_SYN_8(char * buffer)
775 connSyn8 = (CONN_SYN_8*)buffer;
777 assert(sizeof(CONN_SYN_8) == Min8(sizeof(CONN_SYN_8)) && "CONN_SYN_8 is not aligned to 8 bytes");
779 connSyn8->len = sizeof(CONN_SYN_8);
782 SwapBytes(connSyn8->len);
785 strncpy((char*)connSyn8->type, "CONN_SYN", IA_MAX_TYPE_LEN);
786 strncpy((char*)connSyn8->login, login.c_str(), IA_LOGIN_LEN);
788 for (int i = 0; i < DIR_NUM; i++)
790 connSyn8->dirs |= (selectedDirs[i] << i);
792 return sizeof(CONN_SYN_8);
794 //---------------------------------------------------------------------------
795 int IA_CLIENT_PROT::Prepare_CONN_ACK_8(char * buffer)
797 connAck8 = (CONN_ACK_8*)buffer;
799 assert(sizeof(CONN_ACK_8) == Min8(sizeof(CONN_ACK_8)) && "CONN_ACK_8 is not aligned to 8 bytes");
801 connAck8->len = sizeof(CONN_ACK_8);
802 strncpy((char*)connAck8->loginS, login.c_str(), IA_LOGIN_LEN);
803 strncpy((char*)connAck8->type, "CONN_ACK", IA_MAX_TYPE_LEN);
808 SwapBytes(connAck8->len);
809 SwapBytes(connAck8->rnd);
812 return sizeof(CONN_ACK_8);
814 //---------------------------------------------------------------------------
815 int IA_CLIENT_PROT::Prepare_ALIVE_ACK_8(char * buffer)
817 aliveAck8 = (ALIVE_ACK_8*)buffer;
819 assert(Min8(sizeof(ALIVE_ACK_8)) == sizeof(ALIVE_ACK_8) && "ALIVE_ACK_8 is not aligned to 8 bytes");
821 aliveAck8 = (ALIVE_ACK_8*)buffer;
822 aliveAck8->len = sizeof(ALIVE_ACK_8);
823 strncpy((char*)aliveAck8->loginS, login.c_str(), IA_LOGIN_LEN);
824 strncpy((char*)aliveAck8->type, "ALIVE_ACK", IA_MAX_TYPE_LEN);
825 aliveAck8->rnd = ++rnd;
828 SwapBytes(aliveAck8->len);
829 SwapBytes(aliveAck8->rnd);
832 return sizeof(ALIVE_ACK_8);
834 //---------------------------------------------------------------------------
835 int IA_CLIENT_PROT::Prepare_DISCONN_SYN_8(char * buffer)
837 disconnSyn8 = (DISCONN_SYN_8*)buffer;
839 assert(Min8(sizeof(DISCONN_SYN_8)) == sizeof(DISCONN_SYN_8) && "DISCONN_SYN_8 is not aligned to 8 bytes");
841 disconnSyn8->len = sizeof(DISCONN_SYN_8);
844 SwapBytes(disconnSyn8->len);
847 strncpy((char*)disconnSyn8->loginS, login.c_str(), IA_LOGIN_LEN);
848 strncpy((char*)disconnSyn8->type, "DISCONN_SYN", IA_MAX_TYPE_LEN);
849 strncpy((char*)disconnSyn8->login, login.c_str(), IA_LOGIN_LEN);
850 return sizeof(DISCONN_SYN_8);
852 //---------------------------------------------------------------------------
853 int IA_CLIENT_PROT::Prepare_DISCONN_ACK_8(char * buffer)
855 disconnAck8 = (DISCONN_ACK_8*)buffer;
857 assert(Min8(sizeof(DISCONN_ACK_8)) == sizeof(DISCONN_ACK_8) && "DISCONN_ACK_8 is not aligned to 8 bytes");
859 disconnAck8->len = Min8(sizeof(DISCONN_ACK_8));
860 disconnAck8->rnd = rnd + 1;
863 SwapBytes(disconnAck8->len);
864 SwapBytes(disconnAck8->rnd);
867 strncpy((char*)disconnAck8->loginS, login.c_str(), IA_LOGIN_LEN);
868 strncpy((char*)disconnAck8->type, "DISCONN_ACK", IA_MAX_TYPE_LEN);
869 return Min8(sizeof(DISCONN_ACK_8));
871 //---------------------------------------------------------------------------
872 void IA_CLIENT_PROT::SetStatusChangedCb(tpStatusChangedCb p, void * data)
874 pStatusChangedCb = p;
875 statusChangedCbData = data;
877 //---------------------------------------------------------------------------
878 void IA_CLIENT_PROT::SetStatChangedCb(tpStatChangedCb p, void * data)
881 statChangedCbData = data;
883 //---------------------------------------------------------------------------
884 void IA_CLIENT_PROT::SetInfoCb(tpCallBackInfoFn p, void * data)
889 //---------------------------------------------------------------------------
890 void IA_CLIENT_PROT::SetDirNameCb(tpCallBackDirNameFn p, void * data)
893 dirNameCbData = data;
895 //---------------------------------------------------------------------------
896 void IA_CLIENT_PROT::SetErrorCb(tpCallBackErrorFn p, void * data)
901 //---------------------------------------------------------------------------