X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/8c6fa3fbaccc22127280bf77a48fab5a3ee0716e..46b0747592074017ff0ea4b33d4a7194235886e5:/libs/ia/ia.cpp diff --git a/libs/ia/ia.cpp b/libs/ia/ia.cpp new file mode 100644 index 00000000..a05d3061 --- /dev/null +++ b/libs/ia/ia.cpp @@ -0,0 +1,891 @@ +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 1, or (at your option) +** any later version. + +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. + +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + $Author: faust $ + $Revision: 1.15 $ + $Date: 2010/04/16 11:28:03 $ +*/ + +/* +* Author : +* Boris Mikhailenko +* Maxim Mamontov +* Andrey Rakhmanov - bugfixes. +*/ + +//--------------------------------------------------------------------------- + +#ifdef WIN32 +#include +#include +#include +#include +#else +#include +#include +#include +#include +#include +#endif + +#include +#include +#include +#include + +#include "stg/common.h" +#include "stg/ia.h" + +#define IA_NONE (0) +#define IA_CONNECT (1) +#define IA_DISCONNECT (2) + +#define IA_DEBUGPROTO 1 + +#define IA_ID "00100" +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +#ifndef WIN32 +#include +void Sleep(int ms) +{ +long long res = ms * 1000000; +struct timespec ts = {res / 1000000000, res % 1000000000}; +nanosleep(&ts, NULL); +} +//--------------------------------------------------------------------------- +void * RunL(void * data) +{ +sigset_t signalSet; +sigfillset(&signalSet); +pthread_sigmask(SIG_BLOCK, &signalSet, NULL); + +IA_CLIENT_PROT * c = (IA_CLIENT_PROT *)data; +static int a = 0; + +if (a == 0) + { + Sleep(50); + a = 1; + } + +while (c->GetNonstop()) + { + c->Run(); + } +return NULL; +} +//--------------------------------------------------------------------------- +long GetTickCount() +{ +struct timeval tv; +gettimeofday(&tv, NULL); +return tv.tv_sec*1000 + tv.tv_usec/1000; +} +#else +//--------------------------------------------------------------------------- +unsigned long WINAPI RunW(void * data) +{ +IA_CLIENT_PROT * c = (IA_CLIENT_PROT *)data; +while (c->GetNonstop()) + c->Run(); +return 0; +} +//--------------------------------------------------------------------------- +#endif + +namespace +{ + +bool HostNameToIP(const std::string & hostName, uint32_t & ip) +{ +ip = inet_addr(hostName.c_str()); +if (ip == INADDR_NONE) + { + hostent * phe = gethostbyname(hostName.c_str()); + if (phe) + { + ip = *((uint32_t *)phe->h_addr_list[0]); + } + else + { + return false; + } + } + +return true; +} + +} + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +IA_CLIENT_PROT::IA_CLIENT_PROT(const std::string & sn, unsigned short p, + const std::string & ln, uint16_t lp) + : action(IA_NONE), + phase(1), + phaseTime(0), + codeError(0), + nonstop(false), + isNetPrepared(false), + proxyMode(false), + serverName(sn), + port(p), + ip(0), + localName(ln), + localPort(lp), + firstConnect(true), + reconnect(0), + sockr(0), + protNum(0), + userTimeout(60), + aliveTimeout(5), + rnd(0), + pStatusChangedCb(NULL), + pStatChangedCb(NULL), + pInfoCb(NULL), + pErrorCb(NULL), + pDirNameCb(NULL), + statusChangedCbData(NULL), + statChangedCbData(NULL), + infoCbData(NULL), + errorCbData(NULL), + dirNameCbData(NULL), + connSyn8(NULL), + connSynAck8(NULL), + connAck8(NULL), + aliveSyn8(NULL), + aliveAck8(NULL), + disconnSyn8(NULL), + disconnSynAck8(NULL), + disconnAck8(NULL), + info(NULL) +{ +memset(&stat, 0, sizeof(stat)); + +#ifdef WIN32 +WSAStartup(MAKEWORD(2, 0), &wsaData); +#endif + +packetTypes["CONN_SYN"] = CONN_SYN_N; +packetTypes["CONN_SYN_ACK"] = CONN_SYN_ACK_N; +packetTypes["CONN_ACK"] = CONN_ACK_N; +packetTypes["ALIVE_SYN"] = ALIVE_SYN_N; +packetTypes["ALIVE_ACK"] = ALIVE_ACK_N; +packetTypes["DISCONN_SYN"] = DISCONN_SYN_N; +packetTypes["DISCONN_SYN_ACK"] = DISCONN_SYN_ACK_N; +packetTypes["DISCONN_ACK"] = DISCONN_ACK_N; +packetTypes["FIN"] = FIN_N; +packetTypes["ERR"] = ERROR_N; +packetTypes["INFO"] = INFO_N; +packetTypes["INFO_7"] = INFO_7_N; +packetTypes["INFO_8"] = INFO_8_N; + +unsigned char key[IA_PASSWD_LEN]; +memset(key, 0, IA_PASSWD_LEN); +strncpy((char *)key, "pr7Hhen", 8); +Blowfish_Init(&ctxHdr, key, IA_PASSWD_LEN); + +memset(key, 0, IA_PASSWD_LEN); +Blowfish_Init(&ctxPass, key, IA_PASSWD_LEN); + +for (size_t i = 0; i < DIR_NUM; ++i) + { + selectedDirs[i] = false; + } + +servAddr.sin_family = AF_INET; +servAddr.sin_port = htons(port); +servAddr.sin_addr.s_addr = ip; +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::PrepareNet() +{ +/*struct hostent * phe; +unsigned long ip; + +ip = inet_addr(serverName.c_str()); +if (ip == INADDR_NONE) + { + phe = gethostbyname(serverName.c_str()); + if (phe) + { + ip = *((unsigned long*)phe->h_addr_list[0]); + } + else + { + strError = string("Unknown host ") + "\'" + serverName + "\'"; + codeError = IA_GETHOSTBYNAME_ERROR; + if (pErrorCb != NULL) + pErrorCb(strError, IA_GETHOSTBYNAME_ERROR, errorCbData); + } + }*/ + +if (!HostNameToIP(serverName, ip)) + { + ip = 0; + strError = std::string("Unknown host ") + "\'" + serverName + "\'"; + codeError = IA_GETHOSTBYNAME_ERROR; + if (pErrorCb != NULL) + pErrorCb(strError, IA_GETHOSTBYNAME_ERROR, errorCbData); + return; + } + +#ifndef WIN32 +close(sockr); +#else +closesocket(sockr); +#endif + +sockr = socket(AF_INET, SOCK_DGRAM, 0); + +struct sockaddr_in localAddrR; +localAddrR.sin_family = AF_INET; + +if (localPort) + localAddrR.sin_port = htons(localPort); +else + localAddrR.sin_port = htons(port); + +if (!localName.empty()) + { + if (!HostNameToIP(localName, localIP)) + { + strError = std::string("Unknown host ") + "\'" + serverName + "\'"; + codeError = IA_GETHOSTBYNAME_ERROR; + if (pErrorCb != NULL) + pErrorCb(strError, IA_GETHOSTBYNAME_ERROR, errorCbData); + localIP = INADDR_ANY; + } + } +else + { + localIP = INADDR_ANY; + } + +localAddrR.sin_addr.s_addr = localIP; + +servAddr.sin_family = AF_INET; +servAddr.sin_port = htons(port); +servAddr.sin_addr.s_addr = ip; + +int res = bind(sockr, (struct sockaddr*)&localAddrR, sizeof(localAddrR)); +if (res == -1) + { + strError = "bind error"; + codeError = IA_BIND_ERROR; + if (pErrorCb != NULL) + pErrorCb(strError, IA_BIND_ERROR, errorCbData); + return; + } + +#ifdef WIN32 +unsigned long arg = 1; +ioctlsocket(sockr, FIONBIO, &arg); +#else +if (0 != fcntl(sockr, F_SETFL, O_NONBLOCK)) + { + strError = "fcntl error"; + codeError = IA_FCNTL_ERROR; + if (pErrorCb != NULL) + pErrorCb(strError, IA_FCNTL_ERROR, errorCbData); + } +#endif + +} +//--------------------------------------------------------------------------- +IA_CLIENT_PROT::~IA_CLIENT_PROT() +{ +#ifndef WIN32 +close(sockr); +#else +closesocket(sockr); +WSACleanup(); +#endif +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::DeterminatePacketType(const char * buffer) +{ +std::map::iterator pi; +pi = packetTypes.find(buffer); +if (pi == packetTypes.end()) + { + return -1; + } +else + { + return pi->second; + } +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::FillHdr8(char * buffer, unsigned long) +{ +strncpy(buffer, IA_ID, 6); +buffer[IA_MAGIC_LEN] = 0; +buffer[IA_MAGIC_LEN + 1] = IA_PROTO_VER; +strncpy(buffer + sizeof(HDR_8), login.c_str(), IA_LOGIN_LEN); +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Send(char * buffer, int len) +{ +if (!isNetPrepared) + { + PrepareNet(); + isNetPrepared = true; + } + +int db = sizeof(HDR_8); +EncryptString(buffer + db, buffer + db, IA_LOGIN_LEN, &ctxHdr); + +db += IA_LOGIN_LEN; +int encLen = (len - sizeof(HDR_8) - IA_LOGIN_LEN); +EncryptString(buffer + db, buffer + db, encLen, &ctxPass); + +return sendto(sockr, buffer, len, 0, (struct sockaddr*)&servAddr, sizeof(servAddr)); +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Recv(char * buffer, int len) +{ +#ifdef WIN32 +int fromLen; +#else +socklen_t fromLen; +#endif + +struct sockaddr_in addr; +fromLen = sizeof(addr); +int res = recvfrom(sockr, buffer, len, 0, (struct sockaddr*)&addr, &fromLen); + +if (res == -1) + return res; + +if (strcmp(buffer + 4 + sizeof(HDR_8), "ERR")) + DecryptString(buffer, buffer, len, &ctxPass); + +return 0; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::NetSend(int n) +{ +char buffer[2048]; +int msgLen; + +memset(buffer, 0, 2048); + +switch (n) + { + case CONN_SYN_N: + msgLen = Prepare_CONN_SYN_8(buffer); + break; + + case CONN_ACK_N: + msgLen = Prepare_CONN_ACK_8(buffer); + break; + + case ALIVE_ACK_N: + msgLen = Prepare_ALIVE_ACK_8(buffer); + break; + + case DISCONN_SYN_N: + msgLen = Prepare_DISCONN_SYN_8(buffer); + break; + + case DISCONN_ACK_N: + msgLen = Prepare_DISCONN_ACK_8(buffer); + break; + + default: + return -1; + } + +FillHdr8(buffer, 0); +Send(buffer, msgLen); + +return 0; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::NetRecv() +{ +char buffer[2048]; + +if (Recv(buffer, sizeof(buffer)) < 0) + return -1; + +char packetName[20]; +strncpy(packetName, buffer + 12, sizeof(packetName)); +packetName[sizeof(packetName) - 1] = 0; +int pn = DeterminatePacketType(buffer + 12); + +int ret; +switch (pn) + { + case CONN_SYN_ACK_N: + ret = Process_CONN_SYN_ACK_8(buffer); + break; + + case ALIVE_SYN_N: + ret = Process_ALIVE_SYN_8(buffer); + break; + + case DISCONN_SYN_ACK_N: + ret = Process_DISCONN_SYN_ACK_8(buffer); + break; + + case FIN_N: + ret = Process_FIN_8(buffer); + break; + + case INFO_8_N: + ret = Process_INFO_8(buffer); + break; + + case ERROR_N: + ret = Process_ERROR(buffer); + break; + + default: + ret = -1; + } +return ret; +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::Start() +{ +nonstop = true; +#ifdef WIN32 +unsigned long pt; +CreateThread(NULL, 16384, RunW, this, 0, &pt); +#else +pthread_create(&thread, NULL, RunL, this); +#endif +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::Stop() +{ +nonstop = false; +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::Run() +{ +NetRecv(); + +switch (phase) + { + case 1: + if (action == IA_CONNECT) + { + action = IA_NONE; + NetSend(CONN_SYN_N); + phase = 2; + phaseTime = GetTickCount(); + } + if (reconnect && !firstConnect) + { + action = IA_CONNECT; + } + break; + + case 2: + if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout) + { + phase = 1; + phaseTime = GetTickCount(); + if (pStatusChangedCb != NULL) + pStatusChangedCb(0, statusChangedCbData); + } + + if (action == IA_DISCONNECT) + { + action = IA_NONE; + NetSend(DISCONN_SYN_N); + phase = 4; + phaseTime = GetTickCount(); + } + + break; + + case 3: + if ((int)(GetTickCount() - phaseTime)/1000 > userTimeout) + { + phase = 1; + phaseTime = GetTickCount(); + if (pStatusChangedCb != NULL) + pStatusChangedCb(0, statusChangedCbData); + firstConnect = false; + } + + if (action == IA_DISCONNECT) + { + action = IA_NONE; + NetSend(DISCONN_SYN_N); + phase = 4; + phaseTime = GetTickCount(); + } + + break; + + case 4: + if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout) + { + phase=1; + phaseTime = GetTickCount(); + if (pStatusChangedCb != NULL) + pStatusChangedCb(0, statusChangedCbData); + } + + if (action == IA_CONNECT) + { + action = IA_NONE; + NetSend(CONN_SYN_N); + phase = 2; + phaseTime = GetTickCount(); + } + + break; + + case 5: + if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout) + { + phase = 1; + phaseTime = GetTickCount(); + if (pStatusChangedCb != NULL) + pStatusChangedCb(0, statusChangedCbData); + } + + if (action == IA_CONNECT) + { + action = IA_NONE; + NetSend(CONN_SYN_N); + phase = 2; + phaseTime = GetTickCount(); + } + + break; + } +Sleep(20); +return; +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::GetStat(LOADSTAT * ls) +{ +memcpy(ls, &stat, sizeof(stat)); +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::SetServer(const std::string & sn, unsigned short p) +{ +serverName = sn; +port = p; +PrepareNet(); +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::SetLogin(const std::string & l) +{ +login = l; +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::SetPassword(const std::string & p) +{ +password = p; + +unsigned char keyL[IA_PASSWD_LEN]; +memset(keyL, 0, IA_PASSWD_LEN); +strncpy((char *)keyL, password.c_str(), IA_PASSWD_LEN); +Blowfish_Init(&ctxPass, keyL, IA_PASSWD_LEN); +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::SetEnabledDirs(const bool * selectedDirs) +{ +memcpy(IA_CLIENT_PROT::selectedDirs, selectedDirs, sizeof(bool) * DIR_NUM); +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Connect() +{ +action = IA_CONNECT; +return 0; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Disconnect() +{ +firstConnect = true; +action = IA_DISCONNECT; +return 0; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::GetStrError(std::string * error) const +{ +int ret = codeError; +*error = strError; +strError = ""; +codeError = 0; +return ret; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Process_CONN_SYN_ACK_8(const char * buffer) +{ +std::vector dirNames; +connSynAck8 = (CONN_SYN_ACK_8*)buffer; + +#ifdef ARCH_BE +SwapBytes(connSynAck8->len); +SwapBytes(connSynAck8->rnd); +SwapBytes(connSynAck8->userTimeOut); +SwapBytes(connSynAck8->aliveDelay); +#endif + +rnd = connSynAck8->rnd; +userTimeout = connSynAck8->userTimeOut; +aliveTimeout = connSynAck8->aliveDelay; + +for (int i = 0; i < DIR_NUM; i++) + { + dirNames.push_back((const char*)connSynAck8->dirName[i]); + } + +if (pDirNameCb != NULL) + pDirNameCb(dirNames, dirNameCbData); + +NetSend(CONN_ACK_N); +phase = 3; +phaseTime = GetTickCount(); + +return CONN_SYN_ACK_N; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Process_ALIVE_SYN_8(const char * buffer) +{ +aliveSyn8 = (ALIVE_SYN_8*)buffer; + +#ifdef ARCH_BE +SwapBytes(aliveSyn8->len); +SwapBytes(aliveSyn8->rnd); +SwapBytes(aliveSyn8->cash); +SwapBytes(aliveSyn8->status); +for (int i = 0; i < DIR_NUM; ++i) + { + SwapBytes(aliveSyn8->mu[i]); + SwapBytes(aliveSyn8->md[i]); + SwapBytes(aliveSyn8->su[i]); + SwapBytes(aliveSyn8->sd[i]); + } +#endif + +rnd = aliveSyn8->rnd; +memcpy(&stat, (char*)aliveSyn8->mu, sizeof(stat)); + +if (pStatChangedCb != NULL) + pStatChangedCb(stat, statChangedCbData); + +if (pStatusChangedCb != NULL) + pStatusChangedCb(1, statusChangedCbData); +NetSend(ALIVE_ACK_N); +phaseTime = GetTickCount(); + +return ALIVE_SYN_N; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Process_DISCONN_SYN_ACK_8(const char * buffer) +{ +disconnSynAck8 = (DISCONN_SYN_ACK_8*)buffer; + +#ifdef ARCH_BE +SwapBytes(disconnSynAck8->len); +SwapBytes(disconnSynAck8->rnd); +#endif + +rnd = disconnSynAck8->rnd; + +NetSend(DISCONN_ACK_N); +phase = 5; +phaseTime = GetTickCount(); + +return DISCONN_SYN_ACK_N; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Process_FIN_8(const char *) +{ +phase = 1; +phaseTime = GetTickCount(); +if (pStatusChangedCb != NULL) + pStatusChangedCb(0, statusChangedCbData); + +return FIN_N; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Process_INFO_8(const char * buffer) +{ +info = (INFO_8*)buffer; + +#ifdef ARCH_BE +SwapBytes(info->len); +SwapBytes(info->sendTime); +#endif + +if (pInfoCb != NULL) + pInfoCb((char*)info->text, info->infoType, info->showTime, info->sendTime, infoCbData); +return INFO_8_N; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Process_ERROR(const char * buffer) +{ +ERR_8 err; +memcpy(&err, buffer, sizeof(err)); + +#ifdef ARCH_BE +SwapBytes(err.len); +#endif + +KOIToWin((const char*)err.text, &messageText); +if (pErrorCb != NULL) + pErrorCb(messageText, IA_SERVER_ERROR, errorCbData); +phase = 1; +phaseTime = GetTickCount(); +codeError = IA_SERVER_ERROR; + +return ERROR_N; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Prepare_CONN_SYN_8(char * buffer) +{ +connSyn8 = (CONN_SYN_8*)buffer; + +assert(sizeof(CONN_SYN_8) == Min8(sizeof(CONN_SYN_8)) && "CONN_SYN_8 is not aligned to 8 bytes"); + +connSyn8->len = sizeof(CONN_SYN_8); + +#ifdef ARCH_BE +SwapBytes(connSyn8->len); +#endif + +strncpy((char*)connSyn8->type, "CONN_SYN", IA_MAX_TYPE_LEN); +strncpy((char*)connSyn8->login, login.c_str(), IA_LOGIN_LEN); +connSyn8->dirs = 0; +for (int i = 0; i < DIR_NUM; i++) + { + connSyn8->dirs |= (selectedDirs[i] << i); + } +return sizeof(CONN_SYN_8); +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Prepare_CONN_ACK_8(char * buffer) +{ +connAck8 = (CONN_ACK_8*)buffer; + +assert(sizeof(CONN_ACK_8) == Min8(sizeof(CONN_ACK_8)) && "CONN_ACK_8 is not aligned to 8 bytes"); + +connAck8->len = sizeof(CONN_ACK_8); +strncpy((char*)connAck8->loginS, login.c_str(), IA_LOGIN_LEN); +strncpy((char*)connAck8->type, "CONN_ACK", IA_MAX_TYPE_LEN); +rnd++; +connAck8->rnd = rnd; + +#ifdef ARCH_BE +SwapBytes(connAck8->len); +SwapBytes(connAck8->rnd); +#endif + +return sizeof(CONN_ACK_8); +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Prepare_ALIVE_ACK_8(char * buffer) +{ +aliveAck8 = (ALIVE_ACK_8*)buffer; + +assert(Min8(sizeof(ALIVE_ACK_8)) == sizeof(ALIVE_ACK_8) && "ALIVE_ACK_8 is not aligned to 8 bytes"); + +aliveAck8 = (ALIVE_ACK_8*)buffer; +aliveAck8->len = sizeof(ALIVE_ACK_8); +strncpy((char*)aliveAck8->loginS, login.c_str(), IA_LOGIN_LEN); +strncpy((char*)aliveAck8->type, "ALIVE_ACK", IA_MAX_TYPE_LEN); +aliveAck8->rnd = ++rnd; + +#ifdef ARCH_BE +SwapBytes(aliveAck8->len); +SwapBytes(aliveAck8->rnd); +#endif + +return sizeof(ALIVE_ACK_8); +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Prepare_DISCONN_SYN_8(char * buffer) +{ +disconnSyn8 = (DISCONN_SYN_8*)buffer; + +assert(Min8(sizeof(DISCONN_SYN_8)) == sizeof(DISCONN_SYN_8) && "DISCONN_SYN_8 is not aligned to 8 bytes"); + +disconnSyn8->len = sizeof(DISCONN_SYN_8); + +#ifdef ARCH_BE +SwapBytes(disconnSyn8->len); +#endif + +strncpy((char*)disconnSyn8->loginS, login.c_str(), IA_LOGIN_LEN); +strncpy((char*)disconnSyn8->type, "DISCONN_SYN", IA_MAX_TYPE_LEN); +strncpy((char*)disconnSyn8->login, login.c_str(), IA_LOGIN_LEN); +return sizeof(DISCONN_SYN_8); +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Prepare_DISCONN_ACK_8(char * buffer) +{ +disconnAck8 = (DISCONN_ACK_8*)buffer; + +assert(Min8(sizeof(DISCONN_ACK_8)) == sizeof(DISCONN_ACK_8) && "DISCONN_ACK_8 is not aligned to 8 bytes"); + +disconnAck8->len = Min8(sizeof(DISCONN_ACK_8)); +disconnAck8->rnd = rnd + 1; + +#ifdef ARCH_BE +SwapBytes(disconnAck8->len); +SwapBytes(disconnAck8->rnd); +#endif + +strncpy((char*)disconnAck8->loginS, login.c_str(), IA_LOGIN_LEN); +strncpy((char*)disconnAck8->type, "DISCONN_ACK", IA_MAX_TYPE_LEN); +return Min8(sizeof(DISCONN_ACK_8)); +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::SetStatusChangedCb(tpStatusChangedCb p, void * data) +{ +pStatusChangedCb = p; +statusChangedCbData = data; +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::SetStatChangedCb(tpStatChangedCb p, void * data) +{ +pStatChangedCb = p; +statChangedCbData = data; +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::SetInfoCb(tpCallBackInfoFn p, void * data) +{ +pInfoCb = p; +infoCbData = data; +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::SetDirNameCb(tpCallBackDirNameFn p, void * data) +{ +pDirNameCb = p; +dirNameCbData = data; +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::SetErrorCb(tpCallBackErrorFn p, void * data) +{ +pErrorCb = p; +errorCbData = data; +} +//---------------------------------------------------------------------------