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 //---------------------------------------------------------------------------
32 #include "stg/common.h"
48 #include <arpa/inet.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 auto* c = static_cast<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 auto* c = static_cast<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 = *reinterpret_cast<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 m_isNetPrepared(false),
153 m_firstConnect(true),
160 m_pStatusChangedCb(NULL),
161 m_pStatChangedCb(NULL),
165 m_statusChangedCbData(NULL),
166 m_statChangedCbData(NULL),
169 m_dirNameCbData(NULL),
176 m_disconnSynAck8(NULL),
180 memset(&m_stat, 0, sizeof(m_stat));
183 WSAStartup(MAKEWORD(2, 0), &m_wsaData);
186 m_packetTypes["CONN_SYN"] = CONN_SYN_N;
187 m_packetTypes["CONN_SYN_ACK"] = CONN_SYN_ACK_N;
188 m_packetTypes["CONN_ACK"] = CONN_ACK_N;
189 m_packetTypes["ALIVE_SYN"] = ALIVE_SYN_N;
190 m_packetTypes["ALIVE_ACK"] = ALIVE_ACK_N;
191 m_packetTypes["DISCONN_SYN"] = DISCONN_SYN_N;
192 m_packetTypes["DISCONN_SYN_ACK"] = DISCONN_SYN_ACK_N;
193 m_packetTypes["DISCONN_ACK"] = DISCONN_ACK_N;
194 m_packetTypes["FIN"] = FIN_N;
195 m_packetTypes["ERR"] = ERROR_N;
196 m_packetTypes["INFO"] = INFO_N;
197 m_packetTypes["INFO_7"] = INFO_7_N;
198 m_packetTypes["INFO_8"] = INFO_8_N;
200 char key[IA_PASSWD_LEN];
201 memset(key, 0, IA_PASSWD_LEN);
202 strncpy(key, "pr7Hhen", 8);
203 Blowfish_Init(&m_ctxHdr, key, IA_PASSWD_LEN);
205 memset(key, 0, IA_PASSWD_LEN);
206 Blowfish_Init(&m_ctxPass, key, IA_PASSWD_LEN);
208 for (size_t i = 0; i < DIR_NUM; ++i)
209 m_selectedDirs[i] = false;
211 m_servAddr.sin_family = AF_INET;
212 m_servAddr.sin_port = htons(m_port);
213 m_servAddr.sin_addr.s_addr = m_ip;
215 //---------------------------------------------------------------------------
216 void IA_CLIENT_PROT::PrepareNet()
218 /*struct hostent * phe;
221 ip = inet_addr(serverName.c_str());
222 if (ip == INADDR_NONE)
224 phe = gethostbyname(serverName.c_str());
227 ip = *((unsigned long*)phe->h_addr_list[0]);
231 strError = string("Unknown host ") + "\'" + serverName + "\'";
232 codeError = IA_GETHOSTBYNAME_ERROR;
233 if (pErrorCb != NULL)
234 pErrorCb(strError, IA_GETHOSTBYNAME_ERROR, errorCbData);
238 if (!HostNameToIP(m_serverName, m_ip))
241 m_strError = std::string("Unknown host ") + "\'" + m_serverName + "\'";
242 m_codeError = IA_GETHOSTBYNAME_ERROR;
243 if (m_pErrorCb != NULL)
244 m_pErrorCb(m_strError, IA_GETHOSTBYNAME_ERROR, m_errorCbData);
251 closesocket(m_sockr);
254 m_sockr = socket(AF_INET, SOCK_DGRAM, 0);
256 struct sockaddr_in localAddrR;
257 localAddrR.sin_family = AF_INET;
260 localAddrR.sin_port = htons(m_localPort);
262 localAddrR.sin_port = htons(m_port);
264 if (!m_localName.empty())
266 if (!HostNameToIP(m_localName, m_localIP))
268 m_strError = std::string("Unknown host ") + "\'" + m_serverName + "\'";
269 m_codeError = IA_GETHOSTBYNAME_ERROR;
270 if (m_pErrorCb != NULL)
271 m_pErrorCb(m_strError, IA_GETHOSTBYNAME_ERROR, m_errorCbData);
272 m_localIP = INADDR_ANY;
277 m_localIP = INADDR_ANY;
280 localAddrR.sin_addr.s_addr = m_localIP;
282 m_servAddr.sin_family = AF_INET;
283 m_servAddr.sin_port = htons(m_port);
284 m_servAddr.sin_addr.s_addr = m_ip;
286 int res = bind(m_sockr, reinterpret_cast<sockaddr*>(&localAddrR), sizeof(localAddrR));
289 m_strError = "bind error";
290 m_codeError = IA_BIND_ERROR;
291 if (m_pErrorCb != NULL)
292 m_pErrorCb(m_strError, IA_BIND_ERROR, m_errorCbData);
297 unsigned long arg = 1;
298 ioctlsocket(m_sockr, FIONBIO, &arg);
300 if (0 != fcntl(m_sockr, F_SETFL, O_NONBLOCK))
302 m_strError = "fcntl error";
303 m_codeError = IA_FCNTL_ERROR;
304 if (m_pErrorCb != NULL)
305 m_pErrorCb(m_strError, IA_FCNTL_ERROR, m_errorCbData);
310 //---------------------------------------------------------------------------
311 IA_CLIENT_PROT::~IA_CLIENT_PROT()
316 closesocket(m_sockr);
320 //---------------------------------------------------------------------------
321 int IA_CLIENT_PROT::DeterminatePacketType(const char * buffer)
323 std::map<std::string, int>::iterator pi;
324 pi = m_packetTypes.find(buffer);
325 if (pi == m_packetTypes.end())
334 //---------------------------------------------------------------------------
335 void IA_CLIENT_PROT::FillHdr8(char* buffer, unsigned long)
337 strncpy(buffer, IA_ID, 6);
338 buffer[IA_MAGIC_LEN] = 0;
339 buffer[IA_MAGIC_LEN + 1] = IA_PROTO_VER;
340 strncpy(buffer + sizeof(HDR_8), m_login.c_str(), IA_LOGIN_LEN);
342 //---------------------------------------------------------------------------
343 int IA_CLIENT_PROT::Send(char * buffer, int len)
345 if (!m_isNetPrepared)
348 m_isNetPrepared = true;
351 int db = sizeof(HDR_8);
352 EncryptString(buffer + db, buffer + db, IA_LOGIN_LEN, &m_ctxHdr);
355 int encLen = (len - sizeof(HDR_8) - IA_LOGIN_LEN);
356 EncryptString(buffer + db, buffer + db, encLen, &m_ctxPass);
358 return sendto(m_sockr, buffer, len, 0, reinterpret_cast<sockaddr*>(&m_servAddr), sizeof(m_servAddr));
360 //---------------------------------------------------------------------------
361 int IA_CLIENT_PROT::Recv(char * buffer, int len)
369 struct sockaddr_in addr;
370 fromLen = sizeof(addr);
371 int res = recvfrom(m_sockr, buffer, len, 0, reinterpret_cast<sockaddr*>(&addr), &fromLen);
376 if (strcmp(buffer + 4 + sizeof(HDR_8), "ERR"))
377 DecryptString(buffer, buffer, len, &m_ctxPass);
381 //---------------------------------------------------------------------------
382 int IA_CLIENT_PROT::NetSend(int n)
387 memset(buffer, 0, 2048);
392 msgLen = Prepare_CONN_SYN_8(buffer);
396 msgLen = Prepare_CONN_ACK_8(buffer);
400 msgLen = Prepare_ALIVE_ACK_8(buffer);
404 msgLen = Prepare_DISCONN_SYN_8(buffer);
408 msgLen = Prepare_DISCONN_ACK_8(buffer);
416 Send(buffer, msgLen);
420 //---------------------------------------------------------------------------
421 int IA_CLIENT_PROT::NetRecv()
425 if (Recv(buffer, sizeof(buffer)) < 0)
429 strncpy(packetName, buffer + 12, sizeof(packetName));
430 packetName[sizeof(packetName) - 1] = 0;
431 int pn = DeterminatePacketType(buffer + 12);
437 ret = Process_CONN_SYN_ACK_8(buffer);
441 ret = Process_ALIVE_SYN_8(buffer);
444 case DISCONN_SYN_ACK_N:
445 ret = Process_DISCONN_SYN_ACK_8(buffer);
449 ret = Process_FIN_8(buffer);
453 ret = Process_INFO_8(buffer);
457 ret = Process_ERROR(buffer);
465 //---------------------------------------------------------------------------
466 void IA_CLIENT_PROT::Start()
471 CreateThread(NULL, 16384, RunW, this, 0, &pt);
473 pthread_create(&m_thread, NULL, RunL, this);
476 //---------------------------------------------------------------------------
477 void IA_CLIENT_PROT::Stop()
481 //---------------------------------------------------------------------------
482 void IA_CLIENT_PROT::Run()
489 if (m_action == IA_CONNECT)
494 m_phaseTime = GetTickCount();
496 if (m_reconnect && !m_firstConnect)
498 m_action = IA_CONNECT;
503 if (static_cast<int>(GetTickCount() - m_phaseTime)/1000 > m_aliveTimeout)
506 m_phaseTime = GetTickCount();
507 if (m_pStatusChangedCb != NULL)
508 m_pStatusChangedCb(0, m_statusChangedCbData);
511 if (m_action == IA_DISCONNECT)
514 NetSend(DISCONN_SYN_N);
516 m_phaseTime = GetTickCount();
522 if (static_cast<int>(GetTickCount() - m_phaseTime)/1000 > m_userTimeout)
525 m_phaseTime = GetTickCount();
526 if (m_pStatusChangedCb != NULL)
527 m_pStatusChangedCb(0, m_statusChangedCbData);
528 m_firstConnect = false;
531 if (m_action == IA_DISCONNECT)
534 NetSend(DISCONN_SYN_N);
536 m_phaseTime = GetTickCount();
542 if (static_cast<int>(GetTickCount() - m_phaseTime)/1000 > m_aliveTimeout)
545 m_phaseTime = GetTickCount();
546 if (m_pStatusChangedCb != NULL)
547 m_pStatusChangedCb(0, m_statusChangedCbData);
550 if (m_action == IA_CONNECT)
555 m_phaseTime = GetTickCount();
561 if (static_cast<int>(GetTickCount() - m_phaseTime)/1000 > m_aliveTimeout)
564 m_phaseTime = GetTickCount();
565 if (m_pStatusChangedCb != NULL)
566 m_pStatusChangedCb(0, m_statusChangedCbData);
569 if (m_action == IA_CONNECT)
574 m_phaseTime = GetTickCount();
582 //---------------------------------------------------------------------------
583 void IA_CLIENT_PROT::GetStat(LOADSTAT * ls)
585 memcpy(ls, &m_stat, sizeof(m_stat));
587 //---------------------------------------------------------------------------
588 void IA_CLIENT_PROT::SetServer(const std::string & sn, unsigned short p)
594 //---------------------------------------------------------------------------
595 void IA_CLIENT_PROT::SetLogin(const std::string & l)
599 //---------------------------------------------------------------------------
600 void IA_CLIENT_PROT::SetPassword(const std::string & p)
604 char keyL[IA_PASSWD_LEN];
605 memset(keyL, 0, IA_PASSWD_LEN);
606 strncpy(keyL, m_password.c_str(), IA_PASSWD_LEN);
607 Blowfish_Init(&m_ctxPass, keyL, IA_PASSWD_LEN);
609 //---------------------------------------------------------------------------
610 void IA_CLIENT_PROT::SetEnabledDirs(const bool * selectedDirs)
612 memcpy(m_selectedDirs, selectedDirs, sizeof(bool) * DIR_NUM);
614 //---------------------------------------------------------------------------
615 int IA_CLIENT_PROT::Connect()
617 m_action = IA_CONNECT;
620 //---------------------------------------------------------------------------
621 int IA_CLIENT_PROT::Disconnect()
623 m_firstConnect = true;
624 m_action = IA_DISCONNECT;
627 //---------------------------------------------------------------------------
628 int IA_CLIENT_PROT::GetStrError(std::string * error) const
630 int ret = m_codeError;
636 //---------------------------------------------------------------------------
637 int IA_CLIENT_PROT::Process_CONN_SYN_ACK_8(const void* buffer)
639 std::vector<std::string> dirNames;
640 m_connSynAck8 = static_cast<const CONN_SYN_ACK_8*>(buffer);
643 SwapBytes(m_connSynAck8->len);
644 SwapBytes(m_connSynAck8->rnd);
645 SwapBytes(m_connSynAck8->userTimeOut);
646 SwapBytes(m_connSynAck8->aliveDelay);
649 m_rnd = m_connSynAck8->rnd;
650 m_userTimeout = m_connSynAck8->userTimeOut;
651 m_aliveTimeout = m_connSynAck8->aliveDelay;
653 for (int i = 0; i < DIR_NUM; i++)
654 dirNames.push_back(reinterpret_cast<const char*>(m_connSynAck8->dirName[i]));
656 if (m_pDirNameCb != NULL)
657 m_pDirNameCb(dirNames, m_dirNameCbData);
661 m_phaseTime = GetTickCount();
663 return CONN_SYN_ACK_N;
665 //---------------------------------------------------------------------------
666 int IA_CLIENT_PROT::Process_ALIVE_SYN_8(const void* buffer)
668 m_aliveSyn8 = static_cast<const ALIVE_SYN_8*>(buffer);
671 SwapBytes(m_aliveSyn8->len);
672 SwapBytes(m_aliveSyn8->rnd);
673 SwapBytes(m_aliveSyn8->cash);
674 SwapBytes(m_aliveSyn8->status);
675 for (int i = 0; i < DIR_NUM; ++i)
677 SwapBytes(m_aliveSyn8->mu[i]);
678 SwapBytes(m_aliveSyn8->md[i]);
679 SwapBytes(m_aliveSyn8->su[i]);
680 SwapBytes(m_aliveSyn8->sd[i]);
684 m_rnd = m_aliveSyn8->rnd;
685 memcpy(&m_stat, m_aliveSyn8->mu, sizeof(m_stat));
687 if (m_pStatChangedCb != NULL)
688 m_pStatChangedCb(m_stat, m_statChangedCbData);
690 if (m_pStatusChangedCb != NULL)
691 m_pStatusChangedCb(1, m_statusChangedCbData);
692 NetSend(ALIVE_ACK_N);
693 m_phaseTime = GetTickCount();
697 //---------------------------------------------------------------------------
698 int IA_CLIENT_PROT::Process_DISCONN_SYN_ACK_8(const void* buffer)
700 m_disconnSynAck8 = static_cast<const DISCONN_SYN_ACK_8*>(buffer);
703 SwapBytes(m_disconnSynAck8->len);
704 SwapBytes(m_disconnSynAck8->rnd);
707 m_rnd = m_disconnSynAck8->rnd;
709 NetSend(DISCONN_ACK_N);
711 m_phaseTime = GetTickCount();
713 return DISCONN_SYN_ACK_N;
715 //---------------------------------------------------------------------------
716 int IA_CLIENT_PROT::Process_FIN_8(const void*)
719 m_phaseTime = GetTickCount();
720 if (m_pStatusChangedCb != NULL)
721 m_pStatusChangedCb(0, m_statusChangedCbData);
725 //---------------------------------------------------------------------------
726 int IA_CLIENT_PROT::Process_INFO_8(const void* buffer)
728 m_info = static_cast<const INFO_8*>(buffer);
731 SwapBytes(m_info->len);
732 SwapBytes(m_info->sendTime);
735 if (m_pInfoCb != NULL)
736 m_pInfoCb(reinterpret_cast<const char*>(m_info->text), m_info->infoType, m_info->showTime, m_info->sendTime, m_infoCbData);
739 //---------------------------------------------------------------------------
740 int IA_CLIENT_PROT::Process_ERROR(const void* buffer)
743 memcpy(&err, buffer, sizeof(err));
749 KOIToWin(reinterpret_cast<const char*>(err.text), &m_messageText);
750 if (m_pErrorCb != NULL)
751 m_pErrorCb(m_messageText, IA_SERVER_ERROR, m_errorCbData);
753 m_phaseTime = GetTickCount();
754 m_codeError = IA_SERVER_ERROR;
758 //---------------------------------------------------------------------------
759 int IA_CLIENT_PROT::Prepare_CONN_SYN_8(void* buffer)
761 m_connSyn8 = static_cast<CONN_SYN_8*>(buffer);
763 assert(sizeof(CONN_SYN_8) == Min8(sizeof(CONN_SYN_8)) && "CONN_SYN_8 is not aligned to 8 bytes");
765 m_connSyn8->len = sizeof(CONN_SYN_8);
768 SwapBytes(m_connSyn8->len);
771 strncpy(reinterpret_cast<char*>(m_connSyn8->type), "CONN_SYN", IA_MAX_TYPE_LEN);
772 strncpy(reinterpret_cast<char*>(m_connSyn8->login), m_login.c_str(), IA_LOGIN_LEN);
773 m_connSyn8->dirs = 0;
774 for (int i = 0; i < DIR_NUM; i++)
775 m_connSyn8->dirs |= (m_selectedDirs[i] << i);
776 return sizeof(CONN_SYN_8);
778 //---------------------------------------------------------------------------
779 int IA_CLIENT_PROT::Prepare_CONN_ACK_8(void* buffer)
781 m_connAck8 = static_cast<CONN_ACK_8*>(buffer);
783 assert(sizeof(CONN_ACK_8) == Min8(sizeof(CONN_ACK_8)) && "CONN_ACK_8 is not aligned to 8 bytes");
785 m_connAck8->len = sizeof(CONN_ACK_8);
786 strncpy(reinterpret_cast<char*>(m_connAck8->loginS), m_login.c_str(), IA_LOGIN_LEN);
787 strncpy(reinterpret_cast<char*>(m_connAck8->type), "CONN_ACK", IA_MAX_TYPE_LEN);
789 m_connAck8->rnd = m_rnd;
792 SwapBytes(m_connAck8->len);
793 SwapBytes(m_connAck8->rnd);
796 return sizeof(CONN_ACK_8);
798 //---------------------------------------------------------------------------
799 int IA_CLIENT_PROT::Prepare_ALIVE_ACK_8(void* buffer)
801 m_aliveAck8 = static_cast<ALIVE_ACK_8*>(buffer);
803 assert(Min8(sizeof(ALIVE_ACK_8)) == sizeof(ALIVE_ACK_8) && "ALIVE_ACK_8 is not aligned to 8 bytes");
805 m_aliveAck8->len = sizeof(ALIVE_ACK_8);
806 strncpy(reinterpret_cast<char*>(m_aliveAck8->loginS), m_login.c_str(), IA_LOGIN_LEN);
807 strncpy(reinterpret_cast<char*>(m_aliveAck8->type), "ALIVE_ACK", IA_MAX_TYPE_LEN);
808 m_aliveAck8->rnd = ++m_rnd;
811 SwapBytes(m_aliveAck8->len);
812 SwapBytes(m_aliveAck8->rnd);
815 return sizeof(ALIVE_ACK_8);
817 //---------------------------------------------------------------------------
818 int IA_CLIENT_PROT::Prepare_DISCONN_SYN_8(void* buffer)
820 m_disconnSyn8 = static_cast<DISCONN_SYN_8*>(buffer);
822 assert(Min8(sizeof(DISCONN_SYN_8)) == sizeof(DISCONN_SYN_8) && "DISCONN_SYN_8 is not aligned to 8 bytes");
824 m_disconnSyn8->len = sizeof(DISCONN_SYN_8);
827 SwapBytes(m_disconnSyn8->len);
830 strncpy(reinterpret_cast<char*>(m_disconnSyn8->loginS), m_login.c_str(), IA_LOGIN_LEN);
831 strncpy(reinterpret_cast<char*>(m_disconnSyn8->type), "DISCONN_SYN", IA_MAX_TYPE_LEN);
832 strncpy(reinterpret_cast<char*>(m_disconnSyn8->login), m_login.c_str(), IA_LOGIN_LEN);
833 return sizeof(DISCONN_SYN_8);
835 //---------------------------------------------------------------------------
836 int IA_CLIENT_PROT::Prepare_DISCONN_ACK_8(void* buffer)
838 m_disconnAck8 = static_cast<DISCONN_ACK_8*>(buffer);
840 assert(Min8(sizeof(DISCONN_ACK_8)) == sizeof(DISCONN_ACK_8) && "DISCONN_ACK_8 is not aligned to 8 bytes");
842 m_disconnAck8->len = Min8(sizeof(DISCONN_ACK_8));
843 m_disconnAck8->rnd = m_rnd + 1;
846 SwapBytes(m_disconnAck8->len);
847 SwapBytes(m_disconnAck8->rnd);
850 strncpy(reinterpret_cast<char*>(m_disconnAck8->loginS), m_login.c_str(), IA_LOGIN_LEN);
851 strncpy(reinterpret_cast<char*>(m_disconnAck8->type), "DISCONN_ACK", IA_MAX_TYPE_LEN);
852 return Min8(sizeof(DISCONN_ACK_8));
854 //---------------------------------------------------------------------------
855 void IA_CLIENT_PROT::SetStatusChangedCb(tpStatusChangedCb p, void * data)
857 m_pStatusChangedCb = p;
858 m_statusChangedCbData = data;
860 //---------------------------------------------------------------------------
861 void IA_CLIENT_PROT::SetStatChangedCb(tpStatChangedCb p, void * data)
863 m_pStatChangedCb = p;
864 m_statChangedCbData = data;
866 //---------------------------------------------------------------------------
867 void IA_CLIENT_PROT::SetInfoCb(tpCallBackInfoFn p, void * data)
872 //---------------------------------------------------------------------------
873 void IA_CLIENT_PROT::SetDirNameCb(tpCallBackDirNameFn p, void * data)
876 m_dirNameCbData = data;
878 //---------------------------------------------------------------------------
879 void IA_CLIENT_PROT::SetErrorCb(tpCallBackErrorFn p, void * data)
882 m_errorCbData = data;
884 //---------------------------------------------------------------------------