]> git.stg.codes - stg.git/blob - stglibs/ia.lib/ia.cpp
Fixed tests.
[stg.git] / stglibs / ia.lib / 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 #ifdef WIN32
33 #include <winsock2.h>
34 #include <windows.h>
35 #include <winbase.h>
36 #include <winnt.h>
37 #else
38 #include <fcntl.h>
39 #include <netdb.h>
40 #include <arpa/inet.h>
41 #include <unistd.h>
42 #include <csignal>
43 #endif
44
45 #include <cstdio>
46 #include <cstdlib>
47 #include <cstring>
48 #include <cassert>
49
50 #include "stg/common.h"
51 #include "stg/ia.h"
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 IA_CLIENT_PROT * c = (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 IA_CLIENT_PROT * c = (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 = *((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     : action(IA_NONE),
142       phase(1),
143       phaseTime(0),
144       codeError(0),
145       nonstop(false),
146       isNetPrepared(false),
147       proxyMode(false),
148       serverName(sn),
149       port(p),
150       ip(0),
151       localName(ln),
152       localPort(lp),
153       firstConnect(true),
154       reconnect(0),
155       sockr(0),
156       protNum(0),
157       userTimeout(60),
158       aliveTimeout(5),
159       rnd(0),
160       pStatusChangedCb(NULL),
161       pStatChangedCb(NULL),
162       pInfoCb(NULL),
163       pErrorCb(NULL),
164       pDirNameCb(NULL),
165       statusChangedCbData(NULL),
166       statChangedCbData(NULL),
167       infoCbData(NULL),
168       errorCbData(NULL),
169       dirNameCbData(NULL),
170       connSyn8(NULL),
171       connSynAck8(NULL),
172       connAck8(NULL),
173       aliveSyn8(NULL),
174       aliveAck8(NULL),
175       disconnSyn8(NULL),
176       disconnSynAck8(NULL),
177       disconnAck8(NULL),
178       info(NULL)
179 {
180 memset(&stat, 0, sizeof(stat));
181
182 #ifdef WIN32
183 WSAStartup(MAKEWORD(2, 0), &wsaData);
184 #endif
185
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;
199
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);
204
205 memset(key, 0, IA_PASSWD_LEN);
206 Blowfish_Init(&ctxPass, key, IA_PASSWD_LEN);
207
208 for (size_t i = 0; i < DIR_NUM; ++i)
209     {
210     selectedDirs[i] = false;
211     }
212
213 servAddr.sin_family = AF_INET;
214 servAddr.sin_port = htons(port);
215 servAddr.sin_addr.s_addr = ip;
216 }
217 //---------------------------------------------------------------------------
218 void IA_CLIENT_PROT::PrepareNet()
219 {
220 /*struct hostent * phe;
221 unsigned long ip;
222
223 ip = inet_addr(serverName.c_str());
224 if (ip == INADDR_NONE)
225     {
226     phe = gethostbyname(serverName.c_str());
227     if (phe)
228         {
229         ip = *((unsigned long*)phe->h_addr_list[0]);
230         }
231     else
232         {
233         strError = string("Unknown host ") + "\'" + serverName + "\'";
234         codeError = IA_GETHOSTBYNAME_ERROR;
235         if (pErrorCb != NULL)
236             pErrorCb(strError, IA_GETHOSTBYNAME_ERROR, errorCbData);
237         }
238     }*/
239
240 if (!HostNameToIP(serverName, ip))
241     {
242     ip = 0;
243     strError = std::string("Unknown host ") + "\'" + serverName + "\'";
244     codeError = IA_GETHOSTBYNAME_ERROR;
245     if (pErrorCb != NULL)
246         pErrorCb(strError, IA_GETHOSTBYNAME_ERROR, errorCbData);
247     return;
248     }
249
250 #ifndef WIN32
251 close(sockr);
252 #else
253 closesocket(sockr);
254 #endif
255
256 sockr = socket(AF_INET, SOCK_DGRAM, 0);
257
258 struct sockaddr_in  localAddrR;
259 localAddrR.sin_family = AF_INET;
260
261 if (localPort)
262     localAddrR.sin_port = htons(localPort);
263 else
264     localAddrR.sin_port = htons(port);
265
266 if (!localName.empty())
267     {
268     if (!HostNameToIP(localName, localIP))
269         {
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;
275         }
276     }
277 else
278     {
279     localIP = INADDR_ANY;
280     }
281
282 localAddrR.sin_addr.s_addr = localIP;
283
284 servAddr.sin_family = AF_INET;
285 servAddr.sin_port = htons(port);
286 servAddr.sin_addr.s_addr = ip;
287
288 int res = bind(sockr, (struct sockaddr*)&localAddrR, sizeof(localAddrR));
289 if (res == -1)
290     {
291     strError = "bind error";
292     codeError = IA_BIND_ERROR;
293     if (pErrorCb != NULL)
294         pErrorCb(strError, IA_BIND_ERROR, errorCbData);
295     return;
296     }
297
298 #ifdef WIN32
299 unsigned long arg = 1;
300 ioctlsocket(sockr, FIONBIO, &arg);
301 #else
302 if (0 != fcntl(sockr, F_SETFL, O_NONBLOCK))
303     {
304     strError = "fcntl error";
305     codeError = IA_FCNTL_ERROR;
306     if (pErrorCb != NULL)
307         pErrorCb(strError, IA_FCNTL_ERROR, errorCbData);
308     }
309 #endif
310
311 }
312 //---------------------------------------------------------------------------
313 IA_CLIENT_PROT::~IA_CLIENT_PROT()
314 {
315 #ifndef WIN32
316 close(sockr);
317 #else
318 closesocket(sockr);
319 WSACleanup();
320 #endif
321 }
322 //---------------------------------------------------------------------------
323 int IA_CLIENT_PROT::DeterminatePacketType(const char * buffer)
324 {
325 std::map<std::string, int>::iterator pi;
326 pi = packetTypes.find(buffer);
327 if (pi == packetTypes.end())
328     {
329     return -1;
330     }
331 else
332     {
333     return pi->second;
334     }
335 }
336 //---------------------------------------------------------------------------
337 void IA_CLIENT_PROT::FillHdr8(char * buffer, unsigned long)
338 {
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);
343 }
344 //---------------------------------------------------------------------------
345 int IA_CLIENT_PROT::Send(char * buffer, int len)
346 {
347 if (!isNetPrepared)
348     {
349     PrepareNet();
350     isNetPrepared = true;
351     }
352
353 int db = sizeof(HDR_8);
354 for (int i = 0; i < IA_LOGIN_LEN/8; i++)
355     {
356     EncodeString(buffer + db + i * 8, buffer + db + i * 8, &ctxHdr);
357     }
358
359 db += IA_LOGIN_LEN;
360 int encLen = (len - sizeof(HDR_8) - IA_LOGIN_LEN)/8;
361 for (int i = 0; i < encLen; i++)
362     {
363     EncodeString(buffer + db, buffer + db, &ctxPass);
364     db += 8;
365     }
366
367 return sendto(sockr, buffer, len, 0, (struct sockaddr*)&servAddr, sizeof(servAddr));
368 }
369 //---------------------------------------------------------------------------
370 int IA_CLIENT_PROT::Recv(char * buffer, int len)
371 {
372 #ifdef WIN32
373 int fromLen;
374 #else
375 socklen_t fromLen;
376 #endif
377
378 struct sockaddr_in addr;
379 fromLen = sizeof(addr);
380 int res = recvfrom(sockr, buffer, len, 0, (struct sockaddr*)&addr, &fromLen);
381
382 if (res == -1)
383     return res;
384
385 if (strcmp(buffer + 4 + sizeof(HDR_8), "ERR"))
386     {
387     for (int i = 0; i < len / 8; i++)
388         DecodeString(buffer + i * 8, buffer + i * 8, &ctxPass);
389     }
390
391 return 0;
392 }
393 //---------------------------------------------------------------------------
394 int IA_CLIENT_PROT::NetSend(int n)
395 {
396 char buffer[2048];
397 int msgLen;
398
399 memset(buffer, 0, 2048);
400
401 switch (n)
402     {
403     case CONN_SYN_N:
404         msgLen = Prepare_CONN_SYN_8(buffer);
405         break;
406
407     case CONN_ACK_N:
408         msgLen = Prepare_CONN_ACK_8(buffer);
409         break;
410
411     case ALIVE_ACK_N:
412         msgLen = Prepare_ALIVE_ACK_8(buffer);
413         break;
414
415     case DISCONN_SYN_N:
416         msgLen = Prepare_DISCONN_SYN_8(buffer);
417         break;
418
419     case DISCONN_ACK_N:
420         msgLen = Prepare_DISCONN_ACK_8(buffer);
421         break;
422
423     default:
424         return -1;
425     }
426
427 FillHdr8(buffer, 0);
428 Send(buffer, msgLen);
429
430 return 0;
431 }
432 //---------------------------------------------------------------------------
433 int IA_CLIENT_PROT::NetRecv()
434 {
435 char buffer[2048];
436
437 if (Recv(buffer, sizeof(buffer)) < 0)
438     return -1;
439
440 char packetName[20];
441 strncpy(packetName, buffer + 12, sizeof(packetName));
442 packetName[sizeof(packetName) - 1] = 0;
443 int pn = DeterminatePacketType(buffer + 12);
444
445 int ret;
446 switch (pn)
447     {
448     case CONN_SYN_ACK_N:
449         ret = Process_CONN_SYN_ACK_8(buffer);
450         break;
451
452     case ALIVE_SYN_N:
453         ret = Process_ALIVE_SYN_8(buffer);
454         break;
455
456     case DISCONN_SYN_ACK_N:
457         ret = Process_DISCONN_SYN_ACK_8(buffer);
458         break;
459
460     case FIN_N:
461         ret = Process_FIN_8(buffer);
462         break;
463
464     case INFO_8_N:
465         ret = Process_INFO_8(buffer);
466         break;
467
468     case ERROR_N:
469         ret = Process_ERROR(buffer);
470         break;
471
472     default:
473         ret = -1;
474     }
475 return ret;
476 }
477 //---------------------------------------------------------------------------
478 void IA_CLIENT_PROT::Start()
479 {
480 nonstop = true;
481 #ifdef WIN32
482 unsigned long pt;
483 CreateThread(NULL, 16384, RunW, this, 0, &pt);
484 #else
485 pthread_create(&thread, NULL, RunL, this);
486 #endif
487 }
488 //---------------------------------------------------------------------------
489 void IA_CLIENT_PROT::Stop()
490 {
491 nonstop = false;
492 }
493 //---------------------------------------------------------------------------
494 void IA_CLIENT_PROT::Run()
495 {
496 NetRecv();
497
498 switch (phase)
499     {
500     case 1:
501         if (action == IA_CONNECT)
502             {
503             action = IA_NONE;
504             NetSend(CONN_SYN_N);
505             phase = 2;
506             phaseTime = GetTickCount();
507             }
508         if (reconnect && !firstConnect)
509             {
510             action = IA_CONNECT;
511             }
512         break;
513
514     case 2:
515         if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout)
516             {
517             phase = 1;
518             phaseTime = GetTickCount();
519             if (pStatusChangedCb != NULL)
520                 pStatusChangedCb(0, statusChangedCbData);
521             }
522
523         if (action == IA_DISCONNECT)
524             {
525             action = IA_NONE;
526             NetSend(DISCONN_SYN_N);
527             phase = 4;
528             phaseTime = GetTickCount();
529             }
530
531         break;
532
533     case 3:
534         if ((int)(GetTickCount() - phaseTime)/1000 > userTimeout)
535             {
536             phase = 1;
537             phaseTime = GetTickCount();
538             if (pStatusChangedCb != NULL)
539                 pStatusChangedCb(0, statusChangedCbData);
540             firstConnect = false;
541             }
542
543         if (action == IA_DISCONNECT)
544             {
545             action = IA_NONE;
546             NetSend(DISCONN_SYN_N);
547             phase = 4;
548             phaseTime = GetTickCount();
549             }
550
551         break;
552
553     case 4:
554         if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout)
555             {
556             phase=1;
557             phaseTime = GetTickCount();
558             if (pStatusChangedCb != NULL)
559                 pStatusChangedCb(0, statusChangedCbData);
560             }
561
562         if (action == IA_CONNECT)
563             {
564             action = IA_NONE;
565             NetSend(CONN_SYN_N);
566             phase = 2;
567             phaseTime = GetTickCount();
568             }
569
570         break;
571
572     case 5:
573         if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout)
574             {
575             phase = 1;
576             phaseTime = GetTickCount();
577             if (pStatusChangedCb != NULL)
578                 pStatusChangedCb(0, statusChangedCbData);
579             }
580
581         if (action == IA_CONNECT)
582             {
583             action = IA_NONE;
584             NetSend(CONN_SYN_N);
585             phase = 2;
586             phaseTime = GetTickCount();
587             }
588
589         break;
590     }
591 Sleep(20);
592 return;
593 }
594 //---------------------------------------------------------------------------
595 void IA_CLIENT_PROT::GetStat(LOADSTAT * ls)
596 {
597 memcpy(ls, &stat, sizeof(stat));
598 }
599 //---------------------------------------------------------------------------
600 void IA_CLIENT_PROT::SetServer(const std::string & sn, unsigned short p)
601 {
602 serverName = sn;
603 port = p;
604 PrepareNet();
605 }
606 //---------------------------------------------------------------------------
607 void IA_CLIENT_PROT::SetLogin(const std::string & l)
608 {
609 login = l;
610 }
611 //---------------------------------------------------------------------------
612 void IA_CLIENT_PROT::SetPassword(const std::string & p)
613 {
614 password = p;
615
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);
620 }
621 //---------------------------------------------------------------------------
622 void IA_CLIENT_PROT::SetEnabledDirs(const bool * selectedDirs)
623 {
624 memcpy(IA_CLIENT_PROT::selectedDirs, selectedDirs, sizeof(bool) * DIR_NUM);
625 }
626 //---------------------------------------------------------------------------
627 int IA_CLIENT_PROT::Connect()
628 {
629 action = IA_CONNECT;
630 return 0;
631 }
632 //---------------------------------------------------------------------------
633 int IA_CLIENT_PROT::Disconnect()
634 {
635 firstConnect = true;
636 action = IA_DISCONNECT;
637 return 0;
638 }
639 //---------------------------------------------------------------------------
640 int IA_CLIENT_PROT::GetStrError(std::string * error) const
641 {
642 int ret = codeError;
643 *error = strError;
644 strError = "";
645 codeError = 0;
646 return ret;
647 }
648 //---------------------------------------------------------------------------
649 int IA_CLIENT_PROT::Process_CONN_SYN_ACK_8(const char * buffer)
650 {
651 std::vector<std::string> dirNames;
652 connSynAck8 = (CONN_SYN_ACK_8*)buffer;
653
654 #ifdef ARCH_BE
655 SwapBytes(connSynAck8->len);
656 SwapBytes(connSynAck8->rnd);
657 SwapBytes(connSynAck8->userTimeOut);
658 SwapBytes(connSynAck8->aliveDelay);
659 #endif
660
661 rnd = connSynAck8->rnd;
662 userTimeout = connSynAck8->userTimeOut;
663 aliveTimeout = connSynAck8->aliveDelay;
664
665 for (int i = 0; i < DIR_NUM; i++)
666     {
667     dirNames.push_back((const char*)connSynAck8->dirName[i]);
668     }
669
670 if (pDirNameCb != NULL)
671     pDirNameCb(dirNames, dirNameCbData);
672
673 NetSend(CONN_ACK_N);
674 phase = 3;
675 phaseTime = GetTickCount();
676
677 return CONN_SYN_ACK_N;
678 }
679 //---------------------------------------------------------------------------
680 int IA_CLIENT_PROT::Process_ALIVE_SYN_8(const char * buffer)
681 {
682 aliveSyn8 = (ALIVE_SYN_8*)buffer;
683
684 #ifdef ARCH_BE
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)
690     {
691     SwapBytes(aliveSyn8->mu[i]);
692     SwapBytes(aliveSyn8->md[i]);
693     SwapBytes(aliveSyn8->su[i]);
694     SwapBytes(aliveSyn8->sd[i]);
695     }
696 #endif
697
698 rnd = aliveSyn8->rnd;
699 memcpy(&stat, (char*)aliveSyn8->mu, sizeof(stat));
700
701 if (pStatChangedCb != NULL)
702     pStatChangedCb(stat, statChangedCbData);
703
704 if (pStatusChangedCb != NULL)
705     pStatusChangedCb(1, statusChangedCbData);
706 NetSend(ALIVE_ACK_N);
707 phaseTime = GetTickCount();
708
709 return ALIVE_SYN_N;
710 }
711 //---------------------------------------------------------------------------
712 int IA_CLIENT_PROT::Process_DISCONN_SYN_ACK_8(const char * buffer)
713 {
714 disconnSynAck8 = (DISCONN_SYN_ACK_8*)buffer;
715
716 #ifdef ARCH_BE
717 SwapBytes(disconnSynAck8->len);
718 SwapBytes(disconnSynAck8->rnd);
719 #endif
720
721 rnd = disconnSynAck8->rnd;
722
723 NetSend(DISCONN_ACK_N);
724 phase = 5;
725 phaseTime = GetTickCount();
726
727 return DISCONN_SYN_ACK_N;
728 }
729 //---------------------------------------------------------------------------
730 int IA_CLIENT_PROT::Process_FIN_8(const char *)
731 {
732 phase = 1;
733 phaseTime = GetTickCount();
734 if (pStatusChangedCb != NULL)
735     pStatusChangedCb(0, statusChangedCbData);
736
737 return FIN_N;
738 }
739 //---------------------------------------------------------------------------
740 int IA_CLIENT_PROT::Process_INFO_8(const char * buffer)
741 {
742 info = (INFO_8*)buffer;
743
744 #ifdef ARCH_BE
745 SwapBytes(info->len);
746 SwapBytes(info->sendTime);
747 #endif
748
749 if (pInfoCb != NULL)
750     pInfoCb((char*)info->text, info->infoType, info->showTime, info->sendTime, infoCbData);
751 return INFO_8_N;
752 }
753 //---------------------------------------------------------------------------
754 int IA_CLIENT_PROT::Process_ERROR(const char * buffer)
755 {
756 ERR_8 err;
757 memcpy(&err, buffer, sizeof(err));
758
759 #ifdef ARCH_BE
760 SwapBytes(err.len);
761 #endif
762
763 KOIToWin((const char*)err.text, &messageText);
764 if (pErrorCb != NULL)
765     pErrorCb(messageText, IA_SERVER_ERROR, errorCbData);
766 phase = 1;
767 phaseTime = GetTickCount();
768 codeError = IA_SERVER_ERROR;
769
770 return ERROR_N;
771 }
772 //---------------------------------------------------------------------------
773 int IA_CLIENT_PROT::Prepare_CONN_SYN_8(char * buffer)
774 {
775 connSyn8 = (CONN_SYN_8*)buffer;
776
777 assert(sizeof(CONN_SYN_8) == Min8(sizeof(CONN_SYN_8)) && "CONN_SYN_8 is not aligned to 8 bytes");
778
779 connSyn8->len = sizeof(CONN_SYN_8);
780
781 #ifdef ARCH_BE
782 SwapBytes(connSyn8->len);
783 #endif
784
785 strncpy((char*)connSyn8->type, "CONN_SYN", IA_MAX_TYPE_LEN);
786 strncpy((char*)connSyn8->login, login.c_str(), IA_LOGIN_LEN);
787 connSyn8->dirs = 0;
788 for (int i = 0; i < DIR_NUM; i++)
789     {
790     connSyn8->dirs |= (selectedDirs[i] << i);
791     }
792 return sizeof(CONN_SYN_8);
793 }
794 //---------------------------------------------------------------------------
795 int IA_CLIENT_PROT::Prepare_CONN_ACK_8(char * buffer)
796 {
797 connAck8 = (CONN_ACK_8*)buffer;
798
799 assert(sizeof(CONN_ACK_8) == Min8(sizeof(CONN_ACK_8)) && "CONN_ACK_8 is not aligned to 8 bytes");
800
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);
804 rnd++;
805 connAck8->rnd = rnd;
806
807 #ifdef ARCH_BE
808 SwapBytes(connAck8->len);
809 SwapBytes(connAck8->rnd);
810 #endif
811
812 return sizeof(CONN_ACK_8);
813 }
814 //---------------------------------------------------------------------------
815 int IA_CLIENT_PROT::Prepare_ALIVE_ACK_8(char * buffer)
816 {
817 aliveAck8 = (ALIVE_ACK_8*)buffer;
818
819 assert(Min8(sizeof(ALIVE_ACK_8)) == sizeof(ALIVE_ACK_8) && "ALIVE_ACK_8 is not aligned to 8 bytes");
820
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;
826
827 #ifdef ARCH_BE
828 SwapBytes(aliveAck8->len);
829 SwapBytes(aliveAck8->rnd);
830 #endif
831
832 return sizeof(ALIVE_ACK_8);
833 }
834 //---------------------------------------------------------------------------
835 int IA_CLIENT_PROT::Prepare_DISCONN_SYN_8(char * buffer)
836 {
837 disconnSyn8 = (DISCONN_SYN_8*)buffer;
838
839 assert(Min8(sizeof(DISCONN_SYN_8)) == sizeof(DISCONN_SYN_8) && "DISCONN_SYN_8 is not aligned to 8 bytes");
840
841 disconnSyn8->len = sizeof(DISCONN_SYN_8);
842
843 #ifdef ARCH_BE
844 SwapBytes(disconnSyn8->len);
845 #endif
846
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);
851 }
852 //---------------------------------------------------------------------------
853 int IA_CLIENT_PROT::Prepare_DISCONN_ACK_8(char * buffer)
854 {
855 disconnAck8 = (DISCONN_ACK_8*)buffer;
856
857 assert(Min8(sizeof(DISCONN_ACK_8)) == sizeof(DISCONN_ACK_8) && "DISCONN_ACK_8 is not aligned to 8 bytes");
858
859 disconnAck8->len = Min8(sizeof(DISCONN_ACK_8));
860 disconnAck8->rnd = rnd + 1;
861
862 #ifdef ARCH_BE
863 SwapBytes(disconnAck8->len);
864 SwapBytes(disconnAck8->rnd);
865 #endif
866
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));
870 }
871 //---------------------------------------------------------------------------
872 void IA_CLIENT_PROT::SetStatusChangedCb(tpStatusChangedCb p, void * data)
873 {
874 pStatusChangedCb = p;
875 statusChangedCbData = data;
876 }
877 //---------------------------------------------------------------------------
878 void IA_CLIENT_PROT::SetStatChangedCb(tpStatChangedCb p, void * data)
879 {
880 pStatChangedCb = p;
881 statChangedCbData = data;
882 }
883 //---------------------------------------------------------------------------
884 void IA_CLIENT_PROT::SetInfoCb(tpCallBackInfoFn p, void * data)
885 {
886 pInfoCb = p;
887 infoCbData = data;
888 }
889 //---------------------------------------------------------------------------
890 void IA_CLIENT_PROT::SetDirNameCb(tpCallBackDirNameFn p, void * data)
891 {
892 pDirNameCb = p;
893 dirNameCbData = data;
894 }
895 //---------------------------------------------------------------------------
896 void IA_CLIENT_PROT::SetErrorCb(tpCallBackErrorFn p, void * data)
897 {
898 pErrorCb = p;
899 errorCbData = data;
900 }
901 //---------------------------------------------------------------------------