]> git.stg.codes - stg.git/blob - stglibs/ia.lib/ia.cpp
Added info about new config parameters.
[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 EncryptString(buffer + db, buffer + db, IA_LOGIN_LEN, &ctxHdr);
355
356 db += IA_LOGIN_LEN;
357 int encLen = (len - sizeof(HDR_8) - IA_LOGIN_LEN);
358 EncryptString(buffer + db, buffer + db, encLen, &ctxPass);
359
360 return sendto(sockr, buffer, len, 0, (struct sockaddr*)&servAddr, sizeof(servAddr));
361 }
362 //---------------------------------------------------------------------------
363 int IA_CLIENT_PROT::Recv(char * buffer, int len)
364 {
365 #ifdef WIN32
366 int fromLen;
367 #else
368 socklen_t fromLen;
369 #endif
370
371 struct sockaddr_in addr;
372 fromLen = sizeof(addr);
373 int res = recvfrom(sockr, buffer, len, 0, (struct sockaddr*)&addr, &fromLen);
374
375 if (res == -1)
376     return res;
377
378 if (strcmp(buffer + 4 + sizeof(HDR_8), "ERR"))
379     DecryptString(buffer, buffer, len, &ctxPass);
380
381 return 0;
382 }
383 //---------------------------------------------------------------------------
384 int IA_CLIENT_PROT::NetSend(int n)
385 {
386 char buffer[2048];
387 int msgLen;
388
389 memset(buffer, 0, 2048);
390
391 switch (n)
392     {
393     case CONN_SYN_N:
394         msgLen = Prepare_CONN_SYN_8(buffer);
395         break;
396
397     case CONN_ACK_N:
398         msgLen = Prepare_CONN_ACK_8(buffer);
399         break;
400
401     case ALIVE_ACK_N:
402         msgLen = Prepare_ALIVE_ACK_8(buffer);
403         break;
404
405     case DISCONN_SYN_N:
406         msgLen = Prepare_DISCONN_SYN_8(buffer);
407         break;
408
409     case DISCONN_ACK_N:
410         msgLen = Prepare_DISCONN_ACK_8(buffer);
411         break;
412
413     default:
414         return -1;
415     }
416
417 FillHdr8(buffer, 0);
418 Send(buffer, msgLen);
419
420 return 0;
421 }
422 //---------------------------------------------------------------------------
423 int IA_CLIENT_PROT::NetRecv()
424 {
425 char buffer[2048];
426
427 if (Recv(buffer, sizeof(buffer)) < 0)
428     return -1;
429
430 char packetName[20];
431 strncpy(packetName, buffer + 12, sizeof(packetName));
432 packetName[sizeof(packetName) - 1] = 0;
433 int pn = DeterminatePacketType(buffer + 12);
434
435 int ret;
436 switch (pn)
437     {
438     case CONN_SYN_ACK_N:
439         ret = Process_CONN_SYN_ACK_8(buffer);
440         break;
441
442     case ALIVE_SYN_N:
443         ret = Process_ALIVE_SYN_8(buffer);
444         break;
445
446     case DISCONN_SYN_ACK_N:
447         ret = Process_DISCONN_SYN_ACK_8(buffer);
448         break;
449
450     case FIN_N:
451         ret = Process_FIN_8(buffer);
452         break;
453
454     case INFO_8_N:
455         ret = Process_INFO_8(buffer);
456         break;
457
458     case ERROR_N:
459         ret = Process_ERROR(buffer);
460         break;
461
462     default:
463         ret = -1;
464     }
465 return ret;
466 }
467 //---------------------------------------------------------------------------
468 void IA_CLIENT_PROT::Start()
469 {
470 nonstop = true;
471 #ifdef WIN32
472 unsigned long pt;
473 CreateThread(NULL, 16384, RunW, this, 0, &pt);
474 #else
475 pthread_create(&thread, NULL, RunL, this);
476 #endif
477 }
478 //---------------------------------------------------------------------------
479 void IA_CLIENT_PROT::Stop()
480 {
481 nonstop = false;
482 }
483 //---------------------------------------------------------------------------
484 void IA_CLIENT_PROT::Run()
485 {
486 NetRecv();
487
488 switch (phase)
489     {
490     case 1:
491         if (action == IA_CONNECT)
492             {
493             action = IA_NONE;
494             NetSend(CONN_SYN_N);
495             phase = 2;
496             phaseTime = GetTickCount();
497             }
498         if (reconnect && !firstConnect)
499             {
500             action = IA_CONNECT;
501             }
502         break;
503
504     case 2:
505         if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout)
506             {
507             phase = 1;
508             phaseTime = GetTickCount();
509             if (pStatusChangedCb != NULL)
510                 pStatusChangedCb(0, statusChangedCbData);
511             }
512
513         if (action == IA_DISCONNECT)
514             {
515             action = IA_NONE;
516             NetSend(DISCONN_SYN_N);
517             phase = 4;
518             phaseTime = GetTickCount();
519             }
520
521         break;
522
523     case 3:
524         if ((int)(GetTickCount() - phaseTime)/1000 > userTimeout)
525             {
526             phase = 1;
527             phaseTime = GetTickCount();
528             if (pStatusChangedCb != NULL)
529                 pStatusChangedCb(0, statusChangedCbData);
530             firstConnect = false;
531             }
532
533         if (action == IA_DISCONNECT)
534             {
535             action = IA_NONE;
536             NetSend(DISCONN_SYN_N);
537             phase = 4;
538             phaseTime = GetTickCount();
539             }
540
541         break;
542
543     case 4:
544         if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout)
545             {
546             phase=1;
547             phaseTime = GetTickCount();
548             if (pStatusChangedCb != NULL)
549                 pStatusChangedCb(0, statusChangedCbData);
550             }
551
552         if (action == IA_CONNECT)
553             {
554             action = IA_NONE;
555             NetSend(CONN_SYN_N);
556             phase = 2;
557             phaseTime = GetTickCount();
558             }
559
560         break;
561
562     case 5:
563         if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout)
564             {
565             phase = 1;
566             phaseTime = GetTickCount();
567             if (pStatusChangedCb != NULL)
568                 pStatusChangedCb(0, statusChangedCbData);
569             }
570
571         if (action == IA_CONNECT)
572             {
573             action = IA_NONE;
574             NetSend(CONN_SYN_N);
575             phase = 2;
576             phaseTime = GetTickCount();
577             }
578
579         break;
580     }
581 Sleep(20);
582 return;
583 }
584 //---------------------------------------------------------------------------
585 void IA_CLIENT_PROT::GetStat(LOADSTAT * ls)
586 {
587 memcpy(ls, &stat, sizeof(stat));
588 }
589 //---------------------------------------------------------------------------
590 void IA_CLIENT_PROT::SetServer(const std::string & sn, unsigned short p)
591 {
592 serverName = sn;
593 port = p;
594 PrepareNet();
595 }
596 //---------------------------------------------------------------------------
597 void IA_CLIENT_PROT::SetLogin(const std::string & l)
598 {
599 login = l;
600 }
601 //---------------------------------------------------------------------------
602 void IA_CLIENT_PROT::SetPassword(const std::string & p)
603 {
604 password = p;
605
606 unsigned char keyL[IA_PASSWD_LEN];
607 memset(keyL, 0, IA_PASSWD_LEN);
608 strncpy((char *)keyL, password.c_str(), IA_PASSWD_LEN);
609 Blowfish_Init(&ctxPass, keyL, IA_PASSWD_LEN);
610 }
611 //---------------------------------------------------------------------------
612 void IA_CLIENT_PROT::SetEnabledDirs(const bool * selectedDirs)
613 {
614 memcpy(IA_CLIENT_PROT::selectedDirs, selectedDirs, sizeof(bool) * DIR_NUM);
615 }
616 //---------------------------------------------------------------------------
617 int IA_CLIENT_PROT::Connect()
618 {
619 action = IA_CONNECT;
620 return 0;
621 }
622 //---------------------------------------------------------------------------
623 int IA_CLIENT_PROT::Disconnect()
624 {
625 firstConnect = true;
626 action = IA_DISCONNECT;
627 return 0;
628 }
629 //---------------------------------------------------------------------------
630 int IA_CLIENT_PROT::GetStrError(std::string * error) const
631 {
632 int ret = codeError;
633 *error = strError;
634 strError = "";
635 codeError = 0;
636 return ret;
637 }
638 //---------------------------------------------------------------------------
639 int IA_CLIENT_PROT::Process_CONN_SYN_ACK_8(const char * buffer)
640 {
641 std::vector<std::string> dirNames;
642 connSynAck8 = (CONN_SYN_ACK_8*)buffer;
643
644 #ifdef ARCH_BE
645 SwapBytes(connSynAck8->len);
646 SwapBytes(connSynAck8->rnd);
647 SwapBytes(connSynAck8->userTimeOut);
648 SwapBytes(connSynAck8->aliveDelay);
649 #endif
650
651 rnd = connSynAck8->rnd;
652 userTimeout = connSynAck8->userTimeOut;
653 aliveTimeout = connSynAck8->aliveDelay;
654
655 for (int i = 0; i < DIR_NUM; i++)
656     {
657     dirNames.push_back((const char*)connSynAck8->dirName[i]);
658     }
659
660 if (pDirNameCb != NULL)
661     pDirNameCb(dirNames, dirNameCbData);
662
663 NetSend(CONN_ACK_N);
664 phase = 3;
665 phaseTime = GetTickCount();
666
667 return CONN_SYN_ACK_N;
668 }
669 //---------------------------------------------------------------------------
670 int IA_CLIENT_PROT::Process_ALIVE_SYN_8(const char * buffer)
671 {
672 aliveSyn8 = (ALIVE_SYN_8*)buffer;
673
674 #ifdef ARCH_BE
675 SwapBytes(aliveSyn8->len);
676 SwapBytes(aliveSyn8->rnd);
677 SwapBytes(aliveSyn8->cash);
678 SwapBytes(aliveSyn8->status);
679 for (int i = 0; i < DIR_NUM; ++i)
680     {
681     SwapBytes(aliveSyn8->mu[i]);
682     SwapBytes(aliveSyn8->md[i]);
683     SwapBytes(aliveSyn8->su[i]);
684     SwapBytes(aliveSyn8->sd[i]);
685     }
686 #endif
687
688 rnd = aliveSyn8->rnd;
689 memcpy(&stat, (char*)aliveSyn8->mu, sizeof(stat));
690
691 if (pStatChangedCb != NULL)
692     pStatChangedCb(stat, statChangedCbData);
693
694 if (pStatusChangedCb != NULL)
695     pStatusChangedCb(1, statusChangedCbData);
696 NetSend(ALIVE_ACK_N);
697 phaseTime = GetTickCount();
698
699 return ALIVE_SYN_N;
700 }
701 //---------------------------------------------------------------------------
702 int IA_CLIENT_PROT::Process_DISCONN_SYN_ACK_8(const char * buffer)
703 {
704 disconnSynAck8 = (DISCONN_SYN_ACK_8*)buffer;
705
706 #ifdef ARCH_BE
707 SwapBytes(disconnSynAck8->len);
708 SwapBytes(disconnSynAck8->rnd);
709 #endif
710
711 rnd = disconnSynAck8->rnd;
712
713 NetSend(DISCONN_ACK_N);
714 phase = 5;
715 phaseTime = GetTickCount();
716
717 return DISCONN_SYN_ACK_N;
718 }
719 //---------------------------------------------------------------------------
720 int IA_CLIENT_PROT::Process_FIN_8(const char *)
721 {
722 phase = 1;
723 phaseTime = GetTickCount();
724 if (pStatusChangedCb != NULL)
725     pStatusChangedCb(0, statusChangedCbData);
726
727 return FIN_N;
728 }
729 //---------------------------------------------------------------------------
730 int IA_CLIENT_PROT::Process_INFO_8(const char * buffer)
731 {
732 info = (INFO_8*)buffer;
733
734 #ifdef ARCH_BE
735 SwapBytes(info->len);
736 SwapBytes(info->sendTime);
737 #endif
738
739 if (pInfoCb != NULL)
740     pInfoCb((char*)info->text, info->infoType, info->showTime, info->sendTime, infoCbData);
741 return INFO_8_N;
742 }
743 //---------------------------------------------------------------------------
744 int IA_CLIENT_PROT::Process_ERROR(const char * buffer)
745 {
746 ERR_8 err;
747 memcpy(&err, buffer, sizeof(err));
748
749 #ifdef ARCH_BE
750 SwapBytes(err.len);
751 #endif
752
753 KOIToWin((const char*)err.text, &messageText);
754 if (pErrorCb != NULL)
755     pErrorCb(messageText, IA_SERVER_ERROR, errorCbData);
756 phase = 1;
757 phaseTime = GetTickCount();
758 codeError = IA_SERVER_ERROR;
759
760 return ERROR_N;
761 }
762 //---------------------------------------------------------------------------
763 int IA_CLIENT_PROT::Prepare_CONN_SYN_8(char * buffer)
764 {
765 connSyn8 = (CONN_SYN_8*)buffer;
766
767 assert(sizeof(CONN_SYN_8) == Min8(sizeof(CONN_SYN_8)) && "CONN_SYN_8 is not aligned to 8 bytes");
768
769 connSyn8->len = sizeof(CONN_SYN_8);
770
771 #ifdef ARCH_BE
772 SwapBytes(connSyn8->len);
773 #endif
774
775 strncpy((char*)connSyn8->type, "CONN_SYN", IA_MAX_TYPE_LEN);
776 strncpy((char*)connSyn8->login, login.c_str(), IA_LOGIN_LEN);
777 connSyn8->dirs = 0;
778 for (int i = 0; i < DIR_NUM; i++)
779     {
780     connSyn8->dirs |= (selectedDirs[i] << i);
781     }
782 return sizeof(CONN_SYN_8);
783 }
784 //---------------------------------------------------------------------------
785 int IA_CLIENT_PROT::Prepare_CONN_ACK_8(char * buffer)
786 {
787 connAck8 = (CONN_ACK_8*)buffer;
788
789 assert(sizeof(CONN_ACK_8) == Min8(sizeof(CONN_ACK_8)) && "CONN_ACK_8 is not aligned to 8 bytes");
790
791 connAck8->len = sizeof(CONN_ACK_8);
792 strncpy((char*)connAck8->loginS, login.c_str(), IA_LOGIN_LEN);
793 strncpy((char*)connAck8->type, "CONN_ACK", IA_MAX_TYPE_LEN);
794 rnd++;
795 connAck8->rnd = rnd;
796
797 #ifdef ARCH_BE
798 SwapBytes(connAck8->len);
799 SwapBytes(connAck8->rnd);
800 #endif
801
802 return sizeof(CONN_ACK_8);
803 }
804 //---------------------------------------------------------------------------
805 int IA_CLIENT_PROT::Prepare_ALIVE_ACK_8(char * buffer)
806 {
807 aliveAck8 = (ALIVE_ACK_8*)buffer;
808
809 assert(Min8(sizeof(ALIVE_ACK_8)) == sizeof(ALIVE_ACK_8) && "ALIVE_ACK_8 is not aligned to 8 bytes");
810
811 aliveAck8 = (ALIVE_ACK_8*)buffer;
812 aliveAck8->len = sizeof(ALIVE_ACK_8);
813 strncpy((char*)aliveAck8->loginS, login.c_str(), IA_LOGIN_LEN);
814 strncpy((char*)aliveAck8->type, "ALIVE_ACK", IA_MAX_TYPE_LEN);
815 aliveAck8->rnd = ++rnd;
816
817 #ifdef ARCH_BE
818 SwapBytes(aliveAck8->len);
819 SwapBytes(aliveAck8->rnd);
820 #endif
821
822 return sizeof(ALIVE_ACK_8);
823 }
824 //---------------------------------------------------------------------------
825 int IA_CLIENT_PROT::Prepare_DISCONN_SYN_8(char * buffer)
826 {
827 disconnSyn8 = (DISCONN_SYN_8*)buffer;
828
829 assert(Min8(sizeof(DISCONN_SYN_8)) == sizeof(DISCONN_SYN_8) && "DISCONN_SYN_8 is not aligned to 8 bytes");
830
831 disconnSyn8->len = sizeof(DISCONN_SYN_8);
832
833 #ifdef ARCH_BE
834 SwapBytes(disconnSyn8->len);
835 #endif
836
837 strncpy((char*)disconnSyn8->loginS, login.c_str(), IA_LOGIN_LEN);
838 strncpy((char*)disconnSyn8->type, "DISCONN_SYN", IA_MAX_TYPE_LEN);
839 strncpy((char*)disconnSyn8->login, login.c_str(), IA_LOGIN_LEN);
840 return sizeof(DISCONN_SYN_8);
841 }
842 //---------------------------------------------------------------------------
843 int IA_CLIENT_PROT::Prepare_DISCONN_ACK_8(char * buffer)
844 {
845 disconnAck8 = (DISCONN_ACK_8*)buffer;
846
847 assert(Min8(sizeof(DISCONN_ACK_8)) == sizeof(DISCONN_ACK_8) && "DISCONN_ACK_8 is not aligned to 8 bytes");
848
849 disconnAck8->len = Min8(sizeof(DISCONN_ACK_8));
850 disconnAck8->rnd = rnd + 1;
851
852 #ifdef ARCH_BE
853 SwapBytes(disconnAck8->len);
854 SwapBytes(disconnAck8->rnd);
855 #endif
856
857 strncpy((char*)disconnAck8->loginS, login.c_str(), IA_LOGIN_LEN);
858 strncpy((char*)disconnAck8->type, "DISCONN_ACK", IA_MAX_TYPE_LEN);
859 return Min8(sizeof(DISCONN_ACK_8));
860 }
861 //---------------------------------------------------------------------------
862 void IA_CLIENT_PROT::SetStatusChangedCb(tpStatusChangedCb p, void * data)
863 {
864 pStatusChangedCb = p;
865 statusChangedCbData = data;
866 }
867 //---------------------------------------------------------------------------
868 void IA_CLIENT_PROT::SetStatChangedCb(tpStatChangedCb p, void * data)
869 {
870 pStatChangedCb = p;
871 statChangedCbData = data;
872 }
873 //---------------------------------------------------------------------------
874 void IA_CLIENT_PROT::SetInfoCb(tpCallBackInfoFn p, void * data)
875 {
876 pInfoCb = p;
877 infoCbData = data;
878 }
879 //---------------------------------------------------------------------------
880 void IA_CLIENT_PROT::SetDirNameCb(tpCallBackDirNameFn p, void * data)
881 {
882 pDirNameCb = p;
883 dirNameCbData = data;
884 }
885 //---------------------------------------------------------------------------
886 void IA_CLIENT_PROT::SetErrorCb(tpCallBackErrorFn p, void * data)
887 {
888 pErrorCb = p;
889 errorCbData = data;
890 }
891 //---------------------------------------------------------------------------