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 * Andrey Rakhmanov <andrey_rakhmanov@yahoo.com> - èñïðàâëåíèå äâóõ áàãîâ.
29 //---------------------------------------------------------------------------
43 #include <sys/types.h>
44 #include <sys/socket.h>
46 #include <netinet/in.h>
47 #include <arpa/inet.h>
52 #include "ia_auth_c.h"
55 #define IA_CONNECT (1)
56 #define IA_DISCONNECT (2)
58 #define IA_DEBUGPROTO 1
61 //---------------------------------------------------------------------------
62 //---------------------------------------------------------------------------
63 //---------------------------------------------------------------------------
66 void * RunL(void * data)
69 IA_CLIENT_PROT * c = (IA_CLIENT_PROT *)data;
78 while (c->GetNonstop())
84 //---------------------------------------------------------------------------
89 //---------------------------------------------------------------------------
93 gettimeofday(&tv, NULL);
94 return tv.tv_sec*1000 + tv.tv_usec/1000;
97 //---------------------------------------------------------------------------
98 unsigned long WINAPI RunW(void * data)
100 IA_CLIENT_PROT * c = (IA_CLIENT_PROT *)data;
101 while (c->GetNonstop())
105 //---------------------------------------------------------------------------
107 //---------------------------------------------------------------------------
108 //---------------------------------------------------------------------------
109 //---------------------------------------------------------------------------
110 IA_CLIENT_PROT::IA_CLIENT_PROT(const string & sn, unsigned short p, uint16_t localPort)
116 isNetPrepared(false),
121 localPort(localPort),
129 pStatusChangedCb(NULL),
130 pStatChangedCb(NULL),
134 statusChangedCbData(NULL),
135 statChangedCbData(NULL),
145 disconnSynAck8(NULL),
149 memset(&stat, 0, sizeof(stat));
152 WSAStartup(MAKEWORD(2, 0), &wsaData);
155 packetTypes["CONN_SYN"] = CONN_SYN_N;
156 packetTypes["CONN_SYN_ACK"] = CONN_SYN_ACK_N;
157 packetTypes["CONN_ACK"] = CONN_ACK_N;
158 packetTypes["ALIVE_SYN"] = ALIVE_SYN_N;
159 packetTypes["ALIVE_ACK"] = ALIVE_ACK_N;
160 packetTypes["DISCONN_SYN"] = DISCONN_SYN_N;
161 packetTypes["DISCONN_SYN_ACK"] = DISCONN_SYN_ACK_N;
162 packetTypes["DISCONN_ACK"] = DISCONN_ACK_N;
163 packetTypes["FIN"] = FIN_N;
164 packetTypes["ERR"] = ERROR_N;
165 packetTypes["INFO"] = INFO_N;
166 packetTypes["INFO_7"] = INFO_7_N;
167 packetTypes["INFO_8"] = INFO_8_N;
169 unsigned char key[IA_PASSWD_LEN];
170 memset(key, 0, IA_PASSWD_LEN);
171 strncpy((char *)key, "pr7Hhen", 8);
172 Blowfish_Init(&ctxHdr, key, IA_PASSWD_LEN);
174 memset(key, 0, IA_PASSWD_LEN);
175 Blowfish_Init(&ctxPass, key, IA_PASSWD_LEN);
177 for (size_t i = 0; i < DIR_NUM; ++i)
179 selectedDirs[i] = false;
182 servAddr.sin_family = AF_INET;
183 servAddr.sin_port = htons(port);
184 servAddr.sin_addr.s_addr = ip;
186 //---------------------------------------------------------------------------
187 void IA_CLIENT_PROT::PrepareNet()
189 struct hostent * phe;
192 ip = inet_addr(serverName.c_str());
193 if (ip == INADDR_NONE)
195 phe = gethostbyname(serverName.c_str());
198 ip = *((unsigned long*)phe->h_addr_list[0]);
202 strError = string("Unknown host ") + "\'" + serverName + "\'";
203 codeError = IA_GETHOSTBYNAME_ERROR;
204 if (pErrorCb != NULL)
205 pErrorCb(strError, IA_GETHOSTBYNAME_ERROR, errorCbData);
215 sockr = socket(AF_INET, SOCK_DGRAM, 0); // Cîêåò ÷åðåç êîòîðûé øëåì è ïðèíèìàåì
217 struct sockaddr_in localAddrR; // Íàø àäðåñ
218 localAddrR.sin_family = AF_INET;
221 localAddrR.sin_port = htons(localPort);
223 localAddrR.sin_port = htons(port);
224 localAddrR.sin_addr.s_addr = inet_addr("0.0.0.0");
226 servAddr.sin_family = AF_INET;
227 servAddr.sin_port = htons(port);
228 servAddr.sin_addr.s_addr = ip;
230 int res = bind(sockr, (struct sockaddr*)&localAddrR, sizeof(localAddrR));
233 strError = "bind error";
234 codeError = IA_BIND_ERROR;
235 if (pErrorCb != NULL)
236 pErrorCb(strError, IA_BIND_ERROR, errorCbData);
241 unsigned long arg = 1;
242 res = ioctlsocket(sockr, FIONBIO, &arg);
244 if (0 != fcntl(sockr, F_SETFL, O_NONBLOCK))
246 strError = "fcntl error";
247 codeError = IA_FCNTL_ERROR;
248 if (pErrorCb != NULL)
249 pErrorCb(strError, IA_FCNTL_ERROR, errorCbData);
254 //---------------------------------------------------------------------------
255 IA_CLIENT_PROT::~IA_CLIENT_PROT()
264 //---------------------------------------------------------------------------
265 int IA_CLIENT_PROT::DeterminatePacketType(const char * buffer)
267 map<string, int>::iterator pi;
268 pi = packetTypes.find(buffer);
269 if (pi == packetTypes.end())
278 //---------------------------------------------------------------------------
279 void IA_CLIENT_PROT::FillHdr8(char * buffer, unsigned long)
281 strncpy(buffer, IA_ID, 6);
282 buffer[IA_MAGIC_LEN] = 0;
283 buffer[IA_MAGIC_LEN + 1] = IA_PROTO_VER;
284 strncpy(buffer + sizeof(HDR_8), login.c_str(), IA_LOGIN_LEN);
286 //---------------------------------------------------------------------------
287 int IA_CLIENT_PROT::Send(char * buffer, int len)
292 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));
302 // Øèôðóåì âñ¸ îñòàëüíîå
304 int encLen = (len - sizeof(HDR_8) - IA_LOGIN_LEN)/8;
305 for (int i = 0; i < encLen; i++)
307 Blowfish_Encrypt(&ctxPass, (uint32_t*)(buffer + db), (uint32_t*)(buffer + db + 4));
311 return sendto(sockr, buffer, len, 0, (struct sockaddr*)&servAddr, sizeof(servAddr));
313 //---------------------------------------------------------------------------
314 int IA_CLIENT_PROT::Recv(char * buffer, int len)
322 struct sockaddr_in addr;
323 fromLen = sizeof(addr);
324 int res = recvfrom(sockr, buffer, len, 0, (struct sockaddr*)&addr, &fromLen);
329 if (strcmp(buffer + 4 + sizeof(HDR_8), "ERR"))
331 for (int i = 0; i < len/8; i++)
332 Blowfish_Decrypt(&ctxPass, (uint32_t*)(buffer + i*8), (uint32_t*)(buffer + i*8 + 4));
337 //---------------------------------------------------------------------------
338 int IA_CLIENT_PROT::NetSend(int n)
343 memset(buffer, 0, 2048);
348 msgLen = Prepare_CONN_SYN_8(buffer);
352 msgLen = Prepare_CONN_ACK_8(buffer);
356 msgLen = Prepare_ALIVE_ACK_8(buffer);
360 msgLen = Prepare_DISCONN_SYN_8(buffer);
364 msgLen = Prepare_DISCONN_ACK_8(buffer);
372 Send(buffer, msgLen);
376 //---------------------------------------------------------------------------
377 int IA_CLIENT_PROT::NetRecv()
381 if (Recv(buffer, sizeof(buffer)) < 0)
385 strncpy(packetName, buffer + 12, sizeof(packetName));
386 packetName[sizeof(packetName) - 1] = 0;
387 int pn = DeterminatePacketType(buffer + 12);
393 ret = Process_CONN_SYN_ACK_8(buffer);
397 ret = Process_ALIVE_SYN_8(buffer);
400 case DISCONN_SYN_ACK_N:
401 ret = Process_DISCONN_SYN_ACK_8(buffer);
405 ret = Process_FIN_8(buffer);
409 ret = Process_INFO_8(buffer);
413 ret = Process_ERROR(buffer);
421 //---------------------------------------------------------------------------
422 void IA_CLIENT_PROT::Start()
427 CreateThread(NULL, 16384, RunW, this, 0, &pt);
429 pthread_create(&thread, NULL, RunL, this);
432 //---------------------------------------------------------------------------
433 void IA_CLIENT_PROT::Stop()
437 //---------------------------------------------------------------------------
438 void IA_CLIENT_PROT::Run()
445 if (action == IA_CONNECT)
450 phaseTime = GetTickCount();
452 if (reconnect && !firstConnect)
459 if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout)
462 phaseTime = GetTickCount();
463 if (pStatusChangedCb != NULL)
464 pStatusChangedCb(0, statusChangedCbData);
467 if (action == IA_DISCONNECT)
470 NetSend(DISCONN_SYN_N);
472 phaseTime = GetTickCount();
478 if ((int)(GetTickCount() - phaseTime)/1000 > userTimeout)
481 phaseTime = GetTickCount();
482 if (pStatusChangedCb != NULL)
483 pStatusChangedCb(0, statusChangedCbData);
484 firstConnect = false;
487 if (action == IA_DISCONNECT)
490 NetSend(DISCONN_SYN_N);
492 phaseTime = GetTickCount();
498 if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout)
501 phaseTime = GetTickCount();
502 if (pStatusChangedCb != NULL)
503 pStatusChangedCb(0, statusChangedCbData);
506 if (action == IA_CONNECT)
511 phaseTime = GetTickCount();
517 if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout)
520 phaseTime = GetTickCount();
521 if (pStatusChangedCb != NULL)
522 pStatusChangedCb(0, statusChangedCbData);
525 if (action == IA_CONNECT)
530 phaseTime = GetTickCount();
538 //---------------------------------------------------------------------------
539 void IA_CLIENT_PROT::GetStat(LOADSTAT * ls)
541 memcpy(ls, &stat, sizeof(stat));
543 //---------------------------------------------------------------------------
544 void IA_CLIENT_PROT::SetServer(const string & sn, unsigned short p)
550 //---------------------------------------------------------------------------
551 void IA_CLIENT_PROT::SetLogin(const string & l)
555 //---------------------------------------------------------------------------
556 void IA_CLIENT_PROT::SetPassword(const string & p)
560 unsigned char keyL[IA_PASSWD_LEN];
561 memset(keyL, 0, IA_PASSWD_LEN);
562 strncpy((char *)keyL, password.c_str(), IA_PASSWD_LEN);
563 Blowfish_Init(&ctxPass, keyL, IA_PASSWD_LEN);
565 //---------------------------------------------------------------------------
566 void IA_CLIENT_PROT::SetEnabledDirs(const bool * selectedDirs)
568 memcpy(IA_CLIENT_PROT::selectedDirs, selectedDirs, sizeof(bool) * DIR_NUM);
570 //---------------------------------------------------------------------------
571 int IA_CLIENT_PROT::Connect()
576 //---------------------------------------------------------------------------
577 int IA_CLIENT_PROT::Disconnect()
580 action = IA_DISCONNECT;
583 //---------------------------------------------------------------------------
584 int IA_CLIENT_PROT::GetStrError(string * error) const
592 //---------------------------------------------------------------------------
593 int IA_CLIENT_PROT::Process_CONN_SYN_ACK_8(const char * buffer)
595 vector<string> dirNames;
596 connSynAck8 = (CONN_SYN_ACK_8*)buffer;
599 SwapBytes(connSynAck8->len);
600 SwapBytes(connSynAck8->rnd);
601 SwapBytes(connSynAck8->userTimeOut);
602 SwapBytes(connSynAck8->aliveDelay);
605 rnd = connSynAck8->rnd;
606 userTimeout = connSynAck8->userTimeOut;
607 aliveTimeout = connSynAck8->aliveDelay;
609 for (int i = 0; i < DIR_NUM; i++)
611 dirNames.push_back((const char*)connSynAck8->dirName[i]);
614 if (pDirNameCb != NULL)
615 pDirNameCb(dirNames, dirNameCbData);
619 phaseTime = GetTickCount();
621 return CONN_SYN_ACK_N;
623 //---------------------------------------------------------------------------
624 int IA_CLIENT_PROT::Process_ALIVE_SYN_8(const char * buffer)
626 aliveSyn8 = (ALIVE_SYN_8*)buffer;
629 SwapBytes(aliveSyn8->len);
630 SwapBytes(aliveSyn8->rnd);
631 SwapBytes(aliveSyn8->cash);
632 SwapBytes(aliveSyn8->status);
633 for (int i = 0; i < DIR_NUM; ++i)
635 SwapBytes(aliveSyn8->mu[i]);
636 SwapBytes(aliveSyn8->md[i]);
637 SwapBytes(aliveSyn8->su[i]);
638 SwapBytes(aliveSyn8->sd[i]);
642 rnd = aliveSyn8->rnd;
643 memcpy(&stat, (char*)aliveSyn8->mu, sizeof(stat));
645 if (pStatChangedCb != NULL)
646 pStatChangedCb(stat, statChangedCbData);
648 if (pStatusChangedCb != NULL)
649 pStatusChangedCb(1, statusChangedCbData);
650 NetSend(ALIVE_ACK_N);
651 phaseTime = GetTickCount();
655 //---------------------------------------------------------------------------
656 int IA_CLIENT_PROT::Process_DISCONN_SYN_ACK_8(const char * buffer)
658 disconnSynAck8 = (DISCONN_SYN_ACK_8*)buffer;
661 SwapBytes(disconnSynAck8->len);
662 SwapBytes(disconnSynAck8->rnd);
665 rnd = disconnSynAck8->rnd;
667 NetSend(DISCONN_ACK_N);
669 phaseTime = GetTickCount();
671 return DISCONN_SYN_ACK_N;
673 //---------------------------------------------------------------------------
674 int IA_CLIENT_PROT::Process_FIN_8(const char *)
677 phaseTime = GetTickCount();
678 if (pStatusChangedCb != NULL)
679 pStatusChangedCb(0, statusChangedCbData);
683 //---------------------------------------------------------------------------
684 int IA_CLIENT_PROT::Process_INFO_8(const char * buffer)
686 info = (INFO_8*)buffer;
689 SwapBytes(info->len);
690 SwapBytes(info->sendTime);
694 pInfoCb((char*)info->text, info->infoType, info->showTime, info->sendTime, infoCbData);
697 //---------------------------------------------------------------------------
698 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 //---------------------------------------------------------------------------