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