]> git.stg.codes - stg.git/blob - libs/ia/ia.cpp
Fight CLang warnings.
[stg.git] / libs / ia / ia.cpp
1 /*
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)
5 ** any later version.
6
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.
11
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.
15 */
16
17 /*
18  $Author: faust $
19  $Revision: 1.15 $
20  $Date: 2010/04/16 11:28:03 $
21 */
22
23 /*
24 * Author :
25 * Boris Mikhailenko <stg34@stargazer.dp.ua>
26 * Maxim Mamontov <faust@stargazer.dp.ua>
27 * Andrey Rakhmanov <andrey_rakhmanov@yahoo.com> - bugfixes.
28 */
29
30 //---------------------------------------------------------------------------
31
32 #include "stg/common.h"
33 #include "stg/ia.h"
34
35 #include <cstdio>
36 #include <cstdlib>
37 #include <cstring>
38 #include <cassert>
39
40 #ifdef WIN32
41 #include <winsock2.h>
42 #include <windows.h>
43 #include <winbase.h>
44 #include <winnt.h>
45 #else
46 #include <fcntl.h>
47 #include <netdb.h>
48 #include <arpa/inet.h>
49 #include <unistd.h>
50 #include <csignal>
51 #endif
52
53 #define IA_NONE            (0)
54 #define IA_CONNECT         (1)
55 #define IA_DISCONNECT      (2)
56
57 #define IA_DEBUGPROTO   1
58
59 #define IA_ID "00100"
60 //---------------------------------------------------------------------------
61 //---------------------------------------------------------------------------
62 //---------------------------------------------------------------------------
63 #ifndef WIN32
64 #include <sys/time.h>
65 void Sleep(int ms)
66 {
67 long long res = ms * 1000000;
68 struct timespec ts = {res / 1000000000, res % 1000000000};
69 nanosleep(&ts, NULL);
70 }
71 //---------------------------------------------------------------------------
72 void * RunL(void * data)
73 {
74 sigset_t signalSet;
75 sigfillset(&signalSet);
76 pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
77
78 auto* c = static_cast<IA_CLIENT_PROT*>(data);
79 static int a = 0;
80
81 if (a == 0)
82     {
83     Sleep(50);
84     a = 1;
85     }
86
87 while (c->GetNonstop())
88     {
89     c->Run();
90     }
91 return NULL;
92 }
93 //---------------------------------------------------------------------------
94 long GetTickCount()
95 {
96 struct timeval tv;
97 gettimeofday(&tv, NULL);
98 return tv.tv_sec*1000 + tv.tv_usec/1000;
99 }
100 #else
101 //---------------------------------------------------------------------------
102 unsigned long WINAPI RunW(void * data)
103 {
104 auto* c = static_cast<IA_CLIENT_PROT*>(data);
105 while (c->GetNonstop())
106     c->Run();
107 return 0;
108 }
109 //---------------------------------------------------------------------------
110 #endif
111
112 namespace
113 {
114
115 bool HostNameToIP(const std::string & hostName, uint32_t & ip)
116 {
117 ip = inet_addr(hostName.c_str());
118 if (ip == INADDR_NONE)
119     {
120     hostent * phe = gethostbyname(hostName.c_str());
121     if (phe)
122         {
123         ip = *reinterpret_cast<uint32_t*>(phe->h_addr_list[0]);
124         }
125     else
126         {
127         return false;
128         }
129     }
130
131 return true;
132 }
133
134 }
135
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)
141     : m_action(IA_NONE),
142       m_phase(1),
143       m_phaseTime(0),
144       m_codeError(0),
145       m_nonstop(false),
146       m_isNetPrepared(false),
147       m_proxyMode(false),
148       m_serverName(sn),
149       m_port(p),
150       m_ip(0),
151       m_localName(ln),
152       m_localPort(lp),
153       m_firstConnect(true),
154       m_reconnect(0),
155       m_sockr(0),
156       m_protNum(0),
157       m_userTimeout(60),
158       m_aliveTimeout(5),
159       m_rnd(0),
160       m_pStatusChangedCb(NULL),
161       m_pStatChangedCb(NULL),
162       m_pInfoCb(NULL),
163       m_pErrorCb(NULL),
164       m_pDirNameCb(NULL),
165       m_statusChangedCbData(NULL),
166       m_statChangedCbData(NULL),
167       m_infoCbData(NULL),
168       m_errorCbData(NULL),
169       m_dirNameCbData(NULL),
170       m_connSyn8(NULL),
171       m_connSynAck8(NULL),
172       m_connAck8(NULL),
173       m_aliveSyn8(NULL),
174       m_aliveAck8(NULL),
175       m_disconnSyn8(NULL),
176       m_disconnSynAck8(NULL),
177       m_disconnAck8(NULL),
178       m_info(NULL)
179 {
180 memset(&m_stat, 0, sizeof(m_stat));
181
182 #ifdef WIN32
183 WSAStartup(MAKEWORD(2, 0), &m_wsaData);
184 #endif
185
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;
199
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);
204
205 memset(key, 0, IA_PASSWD_LEN);
206 Blowfish_Init(&m_ctxPass, key, IA_PASSWD_LEN);
207
208 for (size_t i = 0; i < DIR_NUM; ++i)
209     m_selectedDirs[i] = false;
210
211 m_servAddr.sin_family = AF_INET;
212 m_servAddr.sin_port = htons(m_port);
213 m_servAddr.sin_addr.s_addr = m_ip;
214 }
215 //---------------------------------------------------------------------------
216 void IA_CLIENT_PROT::PrepareNet()
217 {
218 /*struct hostent * phe;
219 unsigned long ip;
220
221 ip = inet_addr(serverName.c_str());
222 if (ip == INADDR_NONE)
223     {
224     phe = gethostbyname(serverName.c_str());
225     if (phe)
226         {
227         ip = *((unsigned long*)phe->h_addr_list[0]);
228         }
229     else
230         {
231         strError = string("Unknown host ") + "\'" + serverName + "\'";
232         codeError = IA_GETHOSTBYNAME_ERROR;
233         if (pErrorCb != NULL)
234             pErrorCb(strError, IA_GETHOSTBYNAME_ERROR, errorCbData);
235         }
236     }*/
237
238 if (!HostNameToIP(m_serverName, m_ip))
239     {
240     m_ip = 0;
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);
245     return;
246     }
247
248 #ifndef WIN32
249 close(m_sockr);
250 #else
251 closesocket(m_sockr);
252 #endif
253
254 m_sockr = socket(AF_INET, SOCK_DGRAM, 0);
255
256 struct sockaddr_in  localAddrR;
257 localAddrR.sin_family = AF_INET;
258
259 if (m_localPort)
260     localAddrR.sin_port = htons(m_localPort);
261 else
262     localAddrR.sin_port = htons(m_port);
263
264 if (!m_localName.empty())
265     {
266     if (!HostNameToIP(m_localName, m_localIP))
267         {
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;
273         }
274     }
275 else
276     {
277     m_localIP = INADDR_ANY;
278     }
279
280 localAddrR.sin_addr.s_addr = m_localIP;
281
282 m_servAddr.sin_family = AF_INET;
283 m_servAddr.sin_port = htons(m_port);
284 m_servAddr.sin_addr.s_addr = m_ip;
285
286 int res = bind(m_sockr, reinterpret_cast<sockaddr*>(&localAddrR), sizeof(localAddrR));
287 if (res == -1)
288     {
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);
293     return;
294     }
295
296 #ifdef WIN32
297 unsigned long arg = 1;
298 ioctlsocket(m_sockr, FIONBIO, &arg);
299 #else
300 if (0 != fcntl(m_sockr, F_SETFL, O_NONBLOCK))
301     {
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);
306     }
307 #endif
308
309 }
310 //---------------------------------------------------------------------------
311 IA_CLIENT_PROT::~IA_CLIENT_PROT()
312 {
313 #ifndef WIN32
314 close(m_sockr);
315 #else
316 closesocket(m_sockr);
317 WSACleanup();
318 #endif
319 }
320 //---------------------------------------------------------------------------
321 int IA_CLIENT_PROT::DeterminatePacketType(const char * buffer)
322 {
323 std::map<std::string, int>::iterator pi;
324 pi = m_packetTypes.find(buffer);
325 if (pi == m_packetTypes.end())
326     {
327     return -1;
328     }
329 else
330     {
331     return pi->second;
332     }
333 }
334 //---------------------------------------------------------------------------
335 void IA_CLIENT_PROT::FillHdr8(char* buffer, unsigned long)
336 {
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);
341 }
342 //---------------------------------------------------------------------------
343 int IA_CLIENT_PROT::Send(char * buffer, int len)
344 {
345 if (!m_isNetPrepared)
346     {
347     PrepareNet();
348     m_isNetPrepared = true;
349     }
350
351 int db = sizeof(HDR_8);
352 EncryptString(buffer + db, buffer + db, IA_LOGIN_LEN, &m_ctxHdr);
353
354 db += IA_LOGIN_LEN;
355 int encLen = (len - sizeof(HDR_8) - IA_LOGIN_LEN);
356 EncryptString(buffer + db, buffer + db, encLen, &m_ctxPass);
357
358 return sendto(m_sockr, buffer, len, 0, reinterpret_cast<sockaddr*>(&m_servAddr), sizeof(m_servAddr));
359 }
360 //---------------------------------------------------------------------------
361 int IA_CLIENT_PROT::Recv(char * buffer, int len)
362 {
363 #ifdef WIN32
364 int fromLen;
365 #else
366 socklen_t fromLen;
367 #endif
368
369 struct sockaddr_in addr;
370 fromLen = sizeof(addr);
371 int res = recvfrom(m_sockr, buffer, len, 0, reinterpret_cast<sockaddr*>(&addr), &fromLen);
372
373 if (res == -1)
374     return res;
375
376 if (strcmp(buffer + 4 + sizeof(HDR_8), "ERR"))
377     DecryptString(buffer, buffer, len, &m_ctxPass);
378
379 return 0;
380 }
381 //---------------------------------------------------------------------------
382 int IA_CLIENT_PROT::NetSend(int n)
383 {
384 char buffer[2048];
385 int msgLen;
386
387 memset(buffer, 0, 2048);
388
389 switch (n)
390     {
391     case CONN_SYN_N:
392         msgLen = Prepare_CONN_SYN_8(buffer);
393         break;
394
395     case CONN_ACK_N:
396         msgLen = Prepare_CONN_ACK_8(buffer);
397         break;
398
399     case ALIVE_ACK_N:
400         msgLen = Prepare_ALIVE_ACK_8(buffer);
401         break;
402
403     case DISCONN_SYN_N:
404         msgLen = Prepare_DISCONN_SYN_8(buffer);
405         break;
406
407     case DISCONN_ACK_N:
408         msgLen = Prepare_DISCONN_ACK_8(buffer);
409         break;
410
411     default:
412         return -1;
413     }
414
415 FillHdr8(buffer, 0);
416 Send(buffer, msgLen);
417
418 return 0;
419 }
420 //---------------------------------------------------------------------------
421 int IA_CLIENT_PROT::NetRecv()
422 {
423 char buffer[2048];
424
425 if (Recv(buffer, sizeof(buffer)) < 0)
426     return -1;
427
428 char packetName[20];
429 strncpy(packetName, buffer + 12, sizeof(packetName));
430 packetName[sizeof(packetName) - 1] = 0;
431 int pn = DeterminatePacketType(buffer + 12);
432
433 int ret;
434 switch (pn)
435     {
436     case CONN_SYN_ACK_N:
437         ret = Process_CONN_SYN_ACK_8(buffer);
438         break;
439
440     case ALIVE_SYN_N:
441         ret = Process_ALIVE_SYN_8(buffer);
442         break;
443
444     case DISCONN_SYN_ACK_N:
445         ret = Process_DISCONN_SYN_ACK_8(buffer);
446         break;
447
448     case FIN_N:
449         ret = Process_FIN_8(buffer);
450         break;
451
452     case INFO_8_N:
453         ret = Process_INFO_8(buffer);
454         break;
455
456     case ERROR_N:
457         ret = Process_ERROR(buffer);
458         break;
459
460     default:
461         ret = -1;
462     }
463 return ret;
464 }
465 //---------------------------------------------------------------------------
466 void IA_CLIENT_PROT::Start()
467 {
468 m_nonstop = true;
469 #ifdef WIN32
470 unsigned long pt;
471 CreateThread(NULL, 16384, RunW, this, 0, &pt);
472 #else
473 pthread_create(&m_thread, NULL, RunL, this);
474 #endif
475 }
476 //---------------------------------------------------------------------------
477 void IA_CLIENT_PROT::Stop()
478 {
479 m_nonstop = false;
480 }
481 //---------------------------------------------------------------------------
482 void IA_CLIENT_PROT::Run()
483 {
484 NetRecv();
485
486 switch (m_phase)
487     {
488     case 1:
489         if (m_action == IA_CONNECT)
490             {
491             m_action = IA_NONE;
492             NetSend(CONN_SYN_N);
493             m_phase = 2;
494             m_phaseTime = GetTickCount();
495             }
496         if (m_reconnect && !m_firstConnect)
497             {
498             m_action = IA_CONNECT;
499             }
500         break;
501
502     case 2:
503         if (static_cast<int>(GetTickCount() - m_phaseTime)/1000 > m_aliveTimeout)
504             {
505             m_phase = 1;
506             m_phaseTime = GetTickCount();
507             if (m_pStatusChangedCb != NULL)
508                 m_pStatusChangedCb(0, m_statusChangedCbData);
509             }
510
511         if (m_action == IA_DISCONNECT)
512             {
513             m_action = IA_NONE;
514             NetSend(DISCONN_SYN_N);
515             m_phase = 4;
516             m_phaseTime = GetTickCount();
517             }
518
519         break;
520
521     case 3:
522         if (static_cast<int>(GetTickCount() - m_phaseTime)/1000 > m_userTimeout)
523             {
524             m_phase = 1;
525             m_phaseTime = GetTickCount();
526             if (m_pStatusChangedCb != NULL)
527                 m_pStatusChangedCb(0, m_statusChangedCbData);
528             m_firstConnect = false;
529             }
530
531         if (m_action == IA_DISCONNECT)
532             {
533             m_action = IA_NONE;
534             NetSend(DISCONN_SYN_N);
535             m_phase = 4;
536             m_phaseTime = GetTickCount();
537             }
538
539         break;
540
541     case 4:
542         if (static_cast<int>(GetTickCount() - m_phaseTime)/1000 > m_aliveTimeout)
543             {
544             m_phase=1;
545             m_phaseTime = GetTickCount();
546             if (m_pStatusChangedCb != NULL)
547                 m_pStatusChangedCb(0, m_statusChangedCbData);
548             }
549
550         if (m_action == IA_CONNECT)
551             {
552             m_action = IA_NONE;
553             NetSend(CONN_SYN_N);
554             m_phase = 2;
555             m_phaseTime = GetTickCount();
556             }
557
558         break;
559
560     case 5:
561         if (static_cast<int>(GetTickCount() - m_phaseTime)/1000 > m_aliveTimeout)
562             {
563             m_phase = 1;
564             m_phaseTime = GetTickCount();
565             if (m_pStatusChangedCb != NULL)
566                 m_pStatusChangedCb(0, m_statusChangedCbData);
567             }
568
569         if (m_action == IA_CONNECT)
570             {
571             m_action = IA_NONE;
572             NetSend(CONN_SYN_N);
573             m_phase = 2;
574             m_phaseTime = GetTickCount();
575             }
576
577         break;
578     }
579 Sleep(20);
580 return;
581 }
582 //---------------------------------------------------------------------------
583 void IA_CLIENT_PROT::GetStat(LOADSTAT * ls)
584 {
585 memcpy(ls, &m_stat, sizeof(m_stat));
586 }
587 //---------------------------------------------------------------------------
588 void IA_CLIENT_PROT::SetServer(const std::string & sn, unsigned short p)
589 {
590 m_serverName = sn;
591 m_port = p;
592 PrepareNet();
593 }
594 //---------------------------------------------------------------------------
595 void IA_CLIENT_PROT::SetLogin(const std::string & l)
596 {
597 m_login = l;
598 }
599 //---------------------------------------------------------------------------
600 void IA_CLIENT_PROT::SetPassword(const std::string & p)
601 {
602 m_password = p;
603
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);
608 }
609 //---------------------------------------------------------------------------
610 void IA_CLIENT_PROT::SetEnabledDirs(const bool * selectedDirs)
611 {
612 memcpy(m_selectedDirs, selectedDirs, sizeof(bool) * DIR_NUM);
613 }
614 //---------------------------------------------------------------------------
615 int IA_CLIENT_PROT::Connect()
616 {
617 m_action = IA_CONNECT;
618 return 0;
619 }
620 //---------------------------------------------------------------------------
621 int IA_CLIENT_PROT::Disconnect()
622 {
623 m_firstConnect = true;
624 m_action = IA_DISCONNECT;
625 return 0;
626 }
627 //---------------------------------------------------------------------------
628 int IA_CLIENT_PROT::GetStrError(std::string * error) const
629 {
630 int ret = m_codeError;
631 *error = m_strError;
632 m_strError = "";
633 m_codeError = 0;
634 return ret;
635 }
636 //---------------------------------------------------------------------------
637 int IA_CLIENT_PROT::Process_CONN_SYN_ACK_8(const void* buffer)
638 {
639 std::vector<std::string> dirNames;
640 m_connSynAck8 = static_cast<const CONN_SYN_ACK_8*>(buffer);
641
642 #ifdef ARCH_BE
643 SwapBytes(m_connSynAck8->len);
644 SwapBytes(m_connSynAck8->rnd);
645 SwapBytes(m_connSynAck8->userTimeOut);
646 SwapBytes(m_connSynAck8->aliveDelay);
647 #endif
648
649 m_rnd = m_connSynAck8->rnd;
650 m_userTimeout = m_connSynAck8->userTimeOut;
651 m_aliveTimeout = m_connSynAck8->aliveDelay;
652
653 for (int i = 0; i < DIR_NUM; i++)
654     dirNames.push_back(reinterpret_cast<const char*>(m_connSynAck8->dirName[i]));
655
656 if (m_pDirNameCb != NULL)
657     m_pDirNameCb(dirNames, m_dirNameCbData);
658
659 NetSend(CONN_ACK_N);
660 m_phase = 3;
661 m_phaseTime = GetTickCount();
662
663 return CONN_SYN_ACK_N;
664 }
665 //---------------------------------------------------------------------------
666 int IA_CLIENT_PROT::Process_ALIVE_SYN_8(const void* buffer)
667 {
668 m_aliveSyn8 = static_cast<const ALIVE_SYN_8*>(buffer);
669
670 #ifdef ARCH_BE
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)
676     {
677     SwapBytes(m_aliveSyn8->mu[i]);
678     SwapBytes(m_aliveSyn8->md[i]);
679     SwapBytes(m_aliveSyn8->su[i]);
680     SwapBytes(m_aliveSyn8->sd[i]);
681     }
682 #endif
683
684 m_rnd = m_aliveSyn8->rnd;
685 memcpy(&m_stat, m_aliveSyn8->mu, sizeof(m_stat));
686
687 if (m_pStatChangedCb != NULL)
688     m_pStatChangedCb(m_stat, m_statChangedCbData);
689
690 if (m_pStatusChangedCb != NULL)
691     m_pStatusChangedCb(1, m_statusChangedCbData);
692 NetSend(ALIVE_ACK_N);
693 m_phaseTime = GetTickCount();
694
695 return ALIVE_SYN_N;
696 }
697 //---------------------------------------------------------------------------
698 int IA_CLIENT_PROT::Process_DISCONN_SYN_ACK_8(const void* buffer)
699 {
700 m_disconnSynAck8 = static_cast<const DISCONN_SYN_ACK_8*>(buffer);
701
702 #ifdef ARCH_BE
703 SwapBytes(m_disconnSynAck8->len);
704 SwapBytes(m_disconnSynAck8->rnd);
705 #endif
706
707 m_rnd = m_disconnSynAck8->rnd;
708
709 NetSend(DISCONN_ACK_N);
710 m_phase = 5;
711 m_phaseTime = GetTickCount();
712
713 return DISCONN_SYN_ACK_N;
714 }
715 //---------------------------------------------------------------------------
716 int IA_CLIENT_PROT::Process_FIN_8(const void*)
717 {
718 m_phase = 1;
719 m_phaseTime = GetTickCount();
720 if (m_pStatusChangedCb != NULL)
721     m_pStatusChangedCb(0, m_statusChangedCbData);
722
723 return FIN_N;
724 }
725 //---------------------------------------------------------------------------
726 int IA_CLIENT_PROT::Process_INFO_8(const void* buffer)
727 {
728 m_info = static_cast<const INFO_8*>(buffer);
729
730 #ifdef ARCH_BE
731 SwapBytes(m_info->len);
732 SwapBytes(m_info->sendTime);
733 #endif
734
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);
737 return INFO_8_N;
738 }
739 //---------------------------------------------------------------------------
740 int IA_CLIENT_PROT::Process_ERROR(const void* buffer)
741 {
742 ERR_8 err;
743 memcpy(&err, buffer, sizeof(err));
744
745 #ifdef ARCH_BE
746 SwapBytes(err.len);
747 #endif
748
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);
752 m_phase = 1;
753 m_phaseTime = GetTickCount();
754 m_codeError = IA_SERVER_ERROR;
755
756 return ERROR_N;
757 }
758 //---------------------------------------------------------------------------
759 int IA_CLIENT_PROT::Prepare_CONN_SYN_8(void* buffer)
760 {
761 m_connSyn8 = static_cast<CONN_SYN_8*>(buffer);
762
763 assert(sizeof(CONN_SYN_8) == Min8(sizeof(CONN_SYN_8)) && "CONN_SYN_8 is not aligned to 8 bytes");
764
765 m_connSyn8->len = sizeof(CONN_SYN_8);
766
767 #ifdef ARCH_BE
768 SwapBytes(m_connSyn8->len);
769 #endif
770
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);
777 }
778 //---------------------------------------------------------------------------
779 int IA_CLIENT_PROT::Prepare_CONN_ACK_8(void* buffer)
780 {
781 m_connAck8 = static_cast<CONN_ACK_8*>(buffer);
782
783 assert(sizeof(CONN_ACK_8) == Min8(sizeof(CONN_ACK_8)) && "CONN_ACK_8 is not aligned to 8 bytes");
784
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);
788 m_rnd++;
789 m_connAck8->rnd = m_rnd;
790
791 #ifdef ARCH_BE
792 SwapBytes(m_connAck8->len);
793 SwapBytes(m_connAck8->rnd);
794 #endif
795
796 return sizeof(CONN_ACK_8);
797 }
798 //---------------------------------------------------------------------------
799 int IA_CLIENT_PROT::Prepare_ALIVE_ACK_8(void* buffer)
800 {
801 m_aliveAck8 = static_cast<ALIVE_ACK_8*>(buffer);
802
803 assert(Min8(sizeof(ALIVE_ACK_8)) == sizeof(ALIVE_ACK_8) && "ALIVE_ACK_8 is not aligned to 8 bytes");
804
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;
809
810 #ifdef ARCH_BE
811 SwapBytes(m_aliveAck8->len);
812 SwapBytes(m_aliveAck8->rnd);
813 #endif
814
815 return sizeof(ALIVE_ACK_8);
816 }
817 //---------------------------------------------------------------------------
818 int IA_CLIENT_PROT::Prepare_DISCONN_SYN_8(void* buffer)
819 {
820 m_disconnSyn8 = static_cast<DISCONN_SYN_8*>(buffer);
821
822 assert(Min8(sizeof(DISCONN_SYN_8)) == sizeof(DISCONN_SYN_8) && "DISCONN_SYN_8 is not aligned to 8 bytes");
823
824 m_disconnSyn8->len = sizeof(DISCONN_SYN_8);
825
826 #ifdef ARCH_BE
827 SwapBytes(m_disconnSyn8->len);
828 #endif
829
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);
834 }
835 //---------------------------------------------------------------------------
836 int IA_CLIENT_PROT::Prepare_DISCONN_ACK_8(void* buffer)
837 {
838 m_disconnAck8 = static_cast<DISCONN_ACK_8*>(buffer);
839
840 assert(Min8(sizeof(DISCONN_ACK_8)) == sizeof(DISCONN_ACK_8) && "DISCONN_ACK_8 is not aligned to 8 bytes");
841
842 m_disconnAck8->len = Min8(sizeof(DISCONN_ACK_8));
843 m_disconnAck8->rnd = m_rnd + 1;
844
845 #ifdef ARCH_BE
846 SwapBytes(m_disconnAck8->len);
847 SwapBytes(m_disconnAck8->rnd);
848 #endif
849
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));
853 }
854 //---------------------------------------------------------------------------
855 void IA_CLIENT_PROT::SetStatusChangedCb(tpStatusChangedCb p, void * data)
856 {
857 m_pStatusChangedCb = p;
858 m_statusChangedCbData = data;
859 }
860 //---------------------------------------------------------------------------
861 void IA_CLIENT_PROT::SetStatChangedCb(tpStatChangedCb p, void * data)
862 {
863 m_pStatChangedCb = p;
864 m_statChangedCbData = data;
865 }
866 //---------------------------------------------------------------------------
867 void IA_CLIENT_PROT::SetInfoCb(tpCallBackInfoFn p, void * data)
868 {
869 m_pInfoCb = p;
870 m_infoCbData = data;
871 }
872 //---------------------------------------------------------------------------
873 void IA_CLIENT_PROT::SetDirNameCb(tpCallBackDirNameFn p, void * data)
874 {
875 m_pDirNameCb = p;
876 m_dirNameCbData = data;
877 }
878 //---------------------------------------------------------------------------
879 void IA_CLIENT_PROT::SetErrorCb(tpCallBackErrorFn p, void * data)
880 {
881 m_pErrorCb = p;
882 m_errorCbData = data;
883 }
884 //---------------------------------------------------------------------------