/*
* PtokaX - hub server for Direct Connect peer to peer network.
* Copyright (C) 2002-2005 Ptaczek, Ptaczek at PtokaX dot org
* Copyright (C) 2004-2022 Petr Kozelka, PPK at PtokaX dot org
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3
* as published by the Free Software Foundation.
* 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, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
#include "stdinc.h"
//---------------------------------------------------------------------------
#include "eventqueue.h"
#include "ServerManager.h"
#include "SettingManager.h"
#include "utility.h"
//---------------------------------------------------------------------------
#ifdef _WIN32
#pragma hdrstop
#endif
//---------------------------------------------------------------------------
#include "RegThread.h"
#ifdef FLYLINKDC_REMOVE_REGISTER_THREAD
//---------------------------------------------------------------------------
RegisterThread * RegisterThread::m_Ptr = NULL;
//---------------------------------------------------------------------------
RegisterThread::RegSocket::RegSocket() : m_ui64TotalShare(0), m_pPrev(NULL), m_pNext(NULL), m_sAddress(NULL), m_pRecvBuf(NULL), m_pSendBuf(NULL), m_pSendBufHead(NULL),
#ifdef _WIN32
m_Sock(INVALID_SOCKET),
#else
m_Sock(-1),
#endif
m_ui32RecvBufLen(0), m_ui32RecvBufSize(0), m_ui32SendBufLen(0), m_ui32TotalUsers(0), m_ui32AddrLen(0)
{
// ...
}
//---------------------------------------------------------------------------
RegisterThread::RegSocket::~RegSocket()
{
free(m_sAddress);
free(m_pRecvBuf);
free(m_pSendBuf);
shutdown_and_close(m_Sock, SHUT_RDWR);
}
//---------------------------------------------------------------------------
RegisterThread::RegisterThread() : m_pRegSockListS(NULL), m_pRegSockListE(NULL), m_ThreadId(0), m_bTerminated(false), m_ui32BytesRead(0), m_ui32BytesSent(0)
{
m_sMsg[0] = '\0';
#ifdef _WIN32
m_hThreadHandle = INVALID_HANDLE_VALUE;
#endif
}
//---------------------------------------------------------------------------
RegisterThread::~RegisterThread()
{
#ifndef _WIN32
if (m_ThreadId != 0)
{
Close();
WaitFor();
}
#endif
ServerManager::m_ui64BytesRead += (uint64_t)m_ui32BytesRead;
ServerManager::m_ui64BytesSent += (uint64_t)m_ui32BytesSent;
RegSocket * cur = NULL,
* next = m_pRegSockListS;
while (next != NULL)
{
cur = next;
next = cur->m_pNext;
delete cur;
}
#ifdef _WIN32
if (m_hThreadHandle != INVALID_HANDLE_VALUE)
{
CloseHandle(m_hThreadHandle);
}
#endif
}
//---------------------------------------------------------------------------
void RegisterThread::Setup(const char * sListAddresses, const uint16_t ui16AddrsLen)
{
// parse all addresses and create individul RegSockets
char *sAddresses = (char *)malloc(ui16AddrsLen + 1);
if (sAddresses == NULL)
{
AppendDebugLogFormat("[MEM] Cannot allocate %hu bytes for sAddresses in RegisterThread::Setup\n", ui16AddrsLen + 1);
return;
}
memcpy(sAddresses, sListAddresses, ui16AddrsLen);
sAddresses[ui16AddrsLen] = '\0';
char *sAddress = sAddresses;
for (uint16_t ui16i = 0; ui16i < ui16AddrsLen; ui16i++)
{
if (sAddresses[ui16i] == ';')
{
sAddresses[ui16i] = '\0';
}
else if (ui16i != ui16AddrsLen - 1)
{
continue;
}
else
{
ui16i++;
}
AddSock(sAddress, (sAddresses + ui16i) - sAddress);
sAddress = sAddresses + ui16i + 1;
}
free(sAddresses);
}
//---------------------------------------------------------------------------
void RegisterThread::AddSock(char * sAddress, const size_t szLen)
{
RegSocket * pNewSock = new (std::nothrow) RegSocket();
if (pNewSock == NULL)
{
AppendDebugLog("%s - [MEM] Cannot allocate pNewSock in RegisterThread::AddSock\n");
return;
}
pNewSock->m_pPrev = NULL;
pNewSock->m_pNext = NULL;
pNewSock->m_sAddress = (char *)malloc(szLen + 1);
if (pNewSock->m_sAddress == NULL)
{
delete pNewSock;
AppendDebugLogFormat("[MEM] Cannot allocate %zu bytes for sAddress in RegisterThread::AddSock\n", szLen+1);
return;
}
pNewSock->m_ui32AddrLen = (uint32_t)szLen;
memcpy(pNewSock->m_sAddress, sAddress, pNewSock->m_ui32AddrLen);
pNewSock->m_sAddress[pNewSock->m_ui32AddrLen] = '\0';
pNewSock->m_pRecvBuf = (char *)malloc(256);
if (pNewSock->m_pRecvBuf == NULL)
{
delete pNewSock;
AppendDebugLog("%s - [MEM] Cannot allocate 256 bytes for sRecvBuf in RegisterThread::AddSock\n");
return;
}
pNewSock->m_pSendBuf = NULL;
pNewSock->m_pSendBufHead = NULL;
pNewSock->m_ui32RecvBufLen = 0;
pNewSock->m_ui32RecvBufSize = 255;
pNewSock->m_ui32SendBufLen = 0;
pNewSock->m_ui32TotalUsers = 0;
pNewSock->m_ui64TotalShare = 0;
if (m_pRegSockListS == NULL)
{
pNewSock->m_pPrev = NULL;
pNewSock->m_pNext = NULL;
m_pRegSockListS = pNewSock;
m_pRegSockListE = pNewSock;
}
else
{
pNewSock->m_pPrev = m_pRegSockListE;
pNewSock->m_pNext = NULL;
m_pRegSockListE->m_pNext = pNewSock;
m_pRegSockListE = pNewSock;
}
}
//---------------------------------------------------------------------------
#ifdef _WIN32
unsigned __stdcall ExecuteRegisterThread(void * pThread)
{
#else
static void* ExecuteRegisterThread(void * pThread)
{
#endif
(reinterpret_cast<RegisterThread *>(pThread))->Run();
return 0;
}
//---------------------------------------------------------------------------
void RegisterThread::Resume()
{
#ifdef _WIN32
m_hThreadHandle = (HANDLE)_beginthreadex(NULL, 0, ExecuteRegisterThread, this, 0, NULL);
if (m_hThreadHandle == 0)
{
#else
int iRet = pthread_create(&m_ThreadId, NULL, ExecuteRegisterThread, this);
if (iRet != 0)
{
#endif
AppendDebugLog("%s - [ERR] Failed to create new RegisterThread\n");
}
}
//---------------------------------------------------------------------------
void RegisterThread::Run()
{
#ifndef _WIN32
struct timespec sleeptime;
sleeptime.tv_sec = 0;
sleeptime.tv_nsec = 1000000;
#endif
RegSocket * cur = NULL,
* next = m_pRegSockListS;
while (m_bTerminated == false && next != NULL)
{
cur = next;
next = cur->m_pNext;
char *port = strchr(cur->m_sAddress, ':');
if (port != NULL)
{
port[0] = '\0';
int32_t iPort = atoi(port + 1);
if (iPort >= 0 && iPort <= 65535)
{
port[0] = ':';
port = NULL;
}
}
struct addrinfo hints;
memset(&hints, 0, sizeof(addrinfo));
hints.ai_socktype = SOCK_STREAM;
if (ServerManager::m_bUseIPv6 == true)
{
hints.ai_family = AF_UNSPEC;
}
else
{
hints.ai_family = AF_INET;
}
struct addrinfo * pResult = NULL;
if (::getaddrinfo(cur->m_sAddress, port != NULL ? port + 1 : "2501", &hints, &pResult) != 0 || (pResult->ai_family != AF_INET && pResult->ai_family != AF_INET6))
{
#ifdef _WIN32
int iError = WSAGetLastError();
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock resolve error %s (%d). (%s)", WSErrorStr(iError), iError, cur->m_sAddress);
#else
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock resolve error (%s)", cur->m_sAddress);
#endif
if (iMsgLen > 0)
{
EventQueue::m_Ptr->AddThread(EventQueue::EVENT_REGSOCK_MSG, m_sMsg);
}
RemoveSock(cur);
delete cur;
if (pResult != NULL)
{
freeaddrinfo(pResult);
}
continue;
}
if (port != NULL)
{
port[0] = ':';
}
// Initialise socket we want to use for connect
#ifdef _WIN32
if ((cur->m_Sock = socket(pResult->ai_family, pResult->ai_socktype, pResult->ai_protocol)) == INVALID_SOCKET)
{
int iError = WSAGetLastError();
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock create error %s (%d). (%s)", WSErrorStr(iError), iError, cur->m_sAddress);
#else
if ((cur->m_Sock = socket(pResult->ai_family, pResult->ai_socktype, pResult->ai_protocol)) == -1)
{
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock create error %d. (%s)", errno, cur->m_sAddress);
#endif
if (iMsgLen > 0)
{
EventQueue::m_Ptr->AddThread(EventQueue::EVENT_REGSOCK_MSG, m_sMsg);
}
RemoveSock(cur);
delete cur;
freeaddrinfo(pResult);
return;
}
// Set the receive buffer
#ifdef FLYLINKDC_USE_SET_SOCKET_BUFFER
#ifdef _WIN32
int32_t bufsize = 1024;
if (setsockopt(cur->m_Sock, SOL_SOCKET, SO_RCVBUF, (char *) &bufsize, sizeof(bufsize)) == SOCKET_ERROR)
{
int iError = WSAGetLastError();
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock recv buff error %s (%d). (%s)", WSErrorStr(iError), iError, cur->m_sAddress);
#else
int bufsize = 1024;
if (setsockopt(cur->m_Sock, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)) == -1)
{
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock recv buff error %d. (%s)", errno, cur->m_sAddress);
#endif
if (iMsgLen > 0)
{
EventQueue::m_Ptr->AddThread(EventQueue::EVENT_REGSOCK_MSG, m_sMsg);
}
RemoveSock(cur);
delete cur;
freeaddrinfo(pResult);
return;
}
// Set the send buffer
bufsize = 2048;
#ifdef _WIN32
if (setsockopt(cur->m_Sock, SOL_SOCKET, SO_SNDBUF, (char *) &bufsize, sizeof(bufsize)) == SOCKET_ERROR)
{
int iError = WSAGetLastError();
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock send buff error %s (%d). (%s)", WSErrorStr(iError), iError, cur->m_sAddress);
#else
if (setsockopt(cur->m_Sock, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)) == -1)
{
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock send buff error %d. (%s)", errno, cur->m_sAddress);
#endif
if (iMsgLen > 0)
{
EventQueue::m_Ptr->AddThread(EventQueue::EVENT_REGSOCK_MSG, m_sMsg);
}
RemoveSock(cur);
delete cur;
freeaddrinfo(pResult);
return;
}
#endif // FLYLINKDC_USE_SET_SOCKET_BUFFER
// Set non-blocking mode
#ifdef _WIN32
uint32_t block = 1;
if (ioctlsocket(cur->m_Sock, FIONBIO, (unsigned long *)&block) == SOCKET_ERROR)
{
int iError = WSAGetLastError();
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock non-block error %s (%d). (%s)", WSErrorStr(iError), iError, cur->m_sAddress);
#else
int oldFlag = fcntl(cur->m_Sock, F_GETFL, 0);
if (fcntl(cur->m_Sock, F_SETFL, oldFlag | O_NONBLOCK) == -1)
{
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock non-block error %d. (%s)", errno, cur->m_sAddress);
#endif
if (iMsgLen > 0)
{
EventQueue::m_Ptr->AddThread(EventQueue::EVENT_REGSOCK_MSG, m_sMsg);
}
RemoveSock(cur);
delete cur;
freeaddrinfo(pResult);
return;
}
// Finally, time to connect ! ;)
#ifdef _WIN32
if (connect(cur->m_Sock, pResult->ai_addr, (int)pResult->ai_addrlen) == SOCKET_ERROR)
{
int iError = WSAGetLastError();
if (iError != WSAEWOULDBLOCK)
{
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock connect error %s (%d). (%s)", WSErrorStr(iError), iError, cur->m_sAddress);
#else
if (connect(cur->m_Sock, pResult->ai_addr, (int)pResult->ai_addrlen) == -1)
{
if (errno != EINPROGRESS)
{
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock connect error %s (%d). (%s)", ErrnoStr(errno), errno, cur->m_sAddress);
#endif
if (iMsgLen > 0)
{
EventQueue::m_Ptr->AddThread(EventQueue::EVENT_REGSOCK_MSG, m_sMsg);
}
RemoveSock(cur);
delete cur;
::freeaddrinfo(pResult);
continue;
}
}
::freeaddrinfo(pResult);
#ifdef _WIN32
::Sleep(1);
#else
nanosleep(&sleeptime, NULL);
#endif
}
uint16_t iLoops = 0;
#ifndef _WIN32
sleeptime.tv_nsec = 75000000;
#endif
while (m_pRegSockListS != NULL && m_bTerminated == false && iLoops < 4000)
{
iLoops++;
next = m_pRegSockListS;
while (next != NULL)
{
cur = next;
next = cur->m_pNext;
if (Receive(cur) == false)
{
RemoveSock(cur);
delete cur;
continue;
}
if (cur->m_ui32SendBufLen > 0)
{
if (Send(cur) == false)
{
RemoveSock(cur);
delete cur;
continue;
}
}
}
#ifdef _WIN32
::Sleep(75);
#else
nanosleep(&sleeptime, NULL);
#endif
}
next = m_pRegSockListS;
while (next != NULL)
{
cur = next;
next = cur->m_pNext;
if (m_bTerminated == false)
{
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock timeout. (%s)", cur->m_sAddress);
if (iMsgLen > 0)
{
EventQueue::m_Ptr->AddThread(EventQueue::EVENT_REGSOCK_MSG, m_sMsg);
}
}
delete cur;
}
m_pRegSockListS = NULL;
m_pRegSockListE = NULL;
}
//---------------------------------------------------------------------------
void RegisterThread::Close()
{
m_bTerminated = true;
}
//---------------------------------------------------------------------------
void RegisterThread::WaitFor()
{
#ifdef _WIN32
WaitForSingleObject(m_hThreadHandle, INFINITE);
#else
if (m_ThreadId != 0)
{
pthread_join(m_ThreadId, NULL);
m_ThreadId = 0;
}
#endif
}
//---------------------------------------------------------------------------
bool RegisterThread::Receive(RegSocket * pSock)
{
if (pSock->m_pRecvBuf == NULL)
{
return true;
}
#ifdef _WIN32
u_long iAvailBytes = 0;
if (ioctlsocket(pSock->m_Sock, FIONREAD, &iAvailBytes) == SOCKET_ERROR)
{
int iError = WSAGetLastError();
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock ioctlsocket(FIONREAD) error %s (%d). (%s)", WSErrorStr(iError), iError, pSock->m_sAddress);
#else
int iAvailBytes = 0;
if (ioctl(pSock->m_Sock, FIONREAD, &iAvailBytes) == -1)
{
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock ioctl(FIONREAD) error %s (%d). (%s)", ErrnoStr(errno), errno, pSock->m_sAddress);
#endif
if (iMsgLen > 0)
{
EventQueue::m_Ptr->AddThread(EventQueue::EVENT_REGSOCK_MSG, m_sMsg);
}
return false;
}
if (iAvailBytes == 0)
{
// we need to ry receive to catch connection error, or if user closed connection
iAvailBytes = 16;
}
else if (iAvailBytes > 1024)
{
// receive max. 1024 bytes to receive buffer
iAvailBytes = 1024;
}
if (pSock->m_ui32RecvBufSize < pSock->m_ui32RecvBufLen + iAvailBytes)
{
size_t szAllignLen = ((pSock->m_ui32RecvBufLen + iAvailBytes + 1) & 0xFFFFFE00) + 0x200;
if (szAllignLen > 2048)
{
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock receive buffer overflow. (%s)", pSock->m_sAddress);
if (iMsgLen > 0)
{
EventQueue::m_Ptr->AddThread(EventQueue::EVENT_REGSOCK_MSG, m_sMsg);
}
return false;
}
char * oldbuf = pSock->m_pRecvBuf;
pSock->m_pRecvBuf = (char *)realloc(oldbuf, szAllignLen);
if (pSock->m_pRecvBuf == NULL)
{
free(oldbuf);
AppendDebugLogFormat("[MEM] Cannot reallocate %zu bytes for sRecvBuf in RegisterThread::Receive\n", szAllignLen);
return false;
}
pSock->m_ui32RecvBufSize = (uint32_t)(szAllignLen - 1);
}
int iBytes = recv(pSock->m_Sock, pSock->m_pRecvBuf + pSock->m_ui32RecvBufLen, pSock->m_ui32RecvBufSize - pSock->m_ui32RecvBufLen, 0);
#ifdef _WIN32
if (iBytes == SOCKET_ERROR)
{
int iError = WSAGetLastError();
if (iError != WSAEWOULDBLOCK)
{
if (iError == WSAENOTCONN)
{
#else
if (iBytes == -1)
{
if (errno != EAGAIN)
{
if (errno == ENOTCONN)
{
#endif
int iErr = 0;
socklen_t iErrLen = sizeof(iErr);
int iRet = getsockopt(pSock->m_Sock, SOL_SOCKET, SO_ERROR, (char *) &iErr, &iErrLen);
#ifdef _WIN32
if (iRet == SOCKET_ERROR)
{
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock getsockopt error %s (%d). (%s)", WSErrorStr(iRet), iRet, pSock->m_sAddress);
#else
if (iRet == -1)
{
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock getsockopt error %d. (%s)", iRet, pSock->m_sAddress);
#endif
if (iMsgLen > 0)
{
EventQueue::m_Ptr->AddThread(EventQueue::EVENT_REGSOCK_MSG, m_sMsg);
}
return false;
}
else if (iErr != 0)
{
#ifdef _WIN32
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock connect error %s (%d). (%s)", WSErrorStr(iErr), iErr, pSock->m_sAddress);
#else
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock connect error %d. (%s)", iErr, pSock->m_sAddress);
#endif
if (iMsgLen > 0)
{
EventQueue::m_Ptr->AddThread(EventQueue::EVENT_REGSOCK_MSG, m_sMsg);
}
return false;
}
return true;
}
#ifdef _WIN32
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock recv error %s (%d). (%s)", WSErrorStr(iError), iError, pSock->m_sAddress);
#else
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock recv error %s (%d). (%s)", ErrnoStr(errno), errno, pSock->m_sAddress);
#endif
if (iMsgLen > 0)
{
EventQueue::m_Ptr->AddThread(EventQueue::EVENT_REGSOCK_MSG, m_sMsg);
}
return false;
}
else
{
return true;
}
}
else if (iBytes == 0)
{
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock closed connection by server. (%s)", pSock->m_sAddress);
if (iMsgLen > 0)
{
EventQueue::m_Ptr->AddThread(EventQueue::EVENT_REGSOCK_MSG, m_sMsg);
}
return false;
}
m_ui32BytesRead += iBytes;
pSock->m_ui32RecvBufLen += iBytes;
pSock->m_pRecvBuf[pSock->m_ui32RecvBufLen] = '\0';
char *sBuffer = pSock->m_pRecvBuf;
for (uint32_t ui32i = 0; ui32i < pSock->m_ui32RecvBufLen; ui32i++)
{
if (pSock->m_pRecvBuf[ui32i] == '|')
{
uint32_t ui32CommandLen = (uint32_t)(((pSock->m_pRecvBuf + ui32i) - sBuffer) + 1);
if (strncmp(sBuffer, "$Lock ", 6) == 0)
{
sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
#ifdef _WIN32
if (getsockname(pSock->m_Sock, (struct sockaddr *) &addr, &addrlen) == SOCKET_ERROR)
{
int iError = WSAGetLastError();
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock local port error %s (%d). (%s)", WSErrorStr(iError), iError, pSock->m_sAddress);
#else
if (getsockname(pSock->m_Sock, (struct sockaddr *) &addr, &addrlen) == -1)
{
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock local port error %d. (%s)", errno, pSock->m_sAddress);
#endif
if (iMsgLen > 0)
{
EventQueue::m_Ptr->AddThread(EventQueue::EVENT_REGSOCK_MSG, m_sMsg);
}
return false;
}
uint16_t ui16port = (uint16_t)ntohs(addr.sin_port);
char cMagic = (char)((ui16port & 0xFF) + ((ui16port >> 8) & 0xFF));
size_t szLen = ui32CommandLen;
// strip the Lock data
pSock->m_pRecvBuf[ui32i] = '\0';
char * pTemp = strchr(sBuffer + 6, ' ');
if (pTemp != NULL)
{
pTemp[0] = '\0';
szLen = pTemp - sBuffer;
}
pSock->m_pRecvBuf[ui32i] = '|';
// Compute the key
memcpy(m_sMsg, "$Key ", 5);
m_sMsg[5] = '\0';
char v;
// first make the crypting stuff
for (size_t szi = 6; szi < szLen; szi++)
{
if (szi == 6)
{
v = sBuffer[szi] ^ sBuffer[szLen] ^ sBuffer[szLen - 1] ^ cMagic;
}
else
{
v = sBuffer[szi] ^ sBuffer[szi - 1];
}
// Swap nibbles (0xF0 = 11110000, 0x0F = 00001111)
v = (char)(((v << 4) & 0xF0) | ((v >> 4) & 0x0F));
switch (v)
{
case 0:
strcat(m_sMsg, "/%DCN000%/");
break;
case 5:
strcat(m_sMsg, "/%DCN005%/");
break;
case 36:
strcat(m_sMsg, "/%DCN036%/");
break;
case 96:
strcat(m_sMsg, "/%DCN096%/");
break;
case 124:
strcat(m_sMsg, "/%DCN124%/");
break;
case 126:
strcat(m_sMsg, "/%DCN126%/");
break;
default:
strncat(m_sMsg, (char *)&v, 1);
break;
}
}
pSock->m_ui32TotalUsers = ServerManager::m_ui32Logged;
pSock->m_ui64TotalShare = ServerManager::m_ui64TotalShare;
strcat(m_sMsg, "|");
SettingManager::m_Ptr->GetText(SETTXT_HUB_NAME, m_sMsg);
strcat(m_sMsg, "|");
SettingManager::m_Ptr->GetText(SETTXT_HUB_ADDRESS, m_sMsg);
uint16_t ui16FirstPort = SettingManager::m_Ptr->GetFirstPort();
if (ui16FirstPort != 411)
{
strcat(m_sMsg, ":");
strcat(m_sMsg, string(ui16FirstPort).c_str());
}
strcat(m_sMsg, "|");
SettingManager::m_Ptr->GetText(SETTXT_HUB_DESCRIPTION, m_sMsg);
strcat(m_sMsg, " |");
szLen = strlen(m_sMsg);
*(m_sMsg + szLen - 4) = 'x';
*(m_sMsg + szLen - 3) = '.';
*(m_sMsg + szLen - 5) = 'p';
*(m_sMsg + szLen - 6) = '.';
if (SettingManager::m_Ptr->GetBool(SETBOOL_ANTI_MOGLO) == true)
{
*(m_sMsg + szLen - 2) = (char)160;
}
strcat(m_sMsg, string(pSock->m_ui32TotalUsers).c_str());
strcat(m_sMsg, "|");
strcat(m_sMsg, string(pSock->m_ui64TotalShare).c_str());
strcat(m_sMsg, "|");
Add2SendBuf(pSock, m_sMsg);
free(pSock->m_pRecvBuf);
pSock->m_pRecvBuf = NULL;
pSock->m_ui32RecvBufLen = 0;
pSock->m_ui32RecvBufSize = 0;
return true;
}
sBuffer += ui32CommandLen;
}
}
pSock->m_ui32RecvBufLen -= (uint32_t)(sBuffer - pSock->m_pRecvBuf);
if (pSock->m_ui32RecvBufLen == 0)
{
pSock->m_pRecvBuf[0] = '\0';
}
else if (pSock->m_ui32RecvBufLen != 1)
{
memmove(pSock->m_pRecvBuf, sBuffer, pSock->m_ui32RecvBufLen);
pSock->m_pRecvBuf[pSock->m_ui32RecvBufLen] = '\0';
}
else
{
if (sBuffer[0] == '|')
{
pSock->m_pRecvBuf[0] = '\0';
pSock->m_ui32RecvBufLen = 0;
}
else
{
pSock->m_pRecvBuf[0] = sBuffer[0];
pSock->m_pRecvBuf[1] = '\0';
}
}
return true;
}
//---------------------------------------------------------------------------
void RegisterThread::Add2SendBuf(RegSocket * pSock, const char * sData)
{
const size_t szLen = strlen(sData);
pSock->m_pSendBuf = (char *)malloc(szLen + 1);
if (pSock->m_pSendBuf == NULL)
{
AppendDebugLogFormat("[MEM] Cannot allocate %zu bytes for sSendBuf in RegisterThread::Add2SendBuf\n", szLen+1);
return;
}
pSock->m_pSendBufHead = pSock->m_pSendBuf;
memcpy(pSock->m_pSendBuf, sData, szLen);
pSock->m_ui32SendBufLen = (uint32_t)szLen;
pSock->m_pSendBuf[pSock->m_ui32SendBufLen] = '\0';
}
//---------------------------------------------------------------------------
bool RegisterThread::Send(RegSocket * pSock)
{
// compute length of unsent data
uint32_t iOffset = (uint32_t)(pSock->m_pSendBufHead - pSock->m_pSendBuf);
#ifdef _WIN32
int32_t iLen = pSock->m_ui32SendBufLen - iOffset;
#else
int iLen = pSock->m_ui32SendBufLen - iOffset;
#endif
int iBytes = send(pSock->m_Sock, pSock->m_pSendBufHead, iLen, 0);
#ifdef _WIN32
if (iBytes == SOCKET_ERROR)
{
int iError = WSAGetLastError();
if (iError != WSAEWOULDBLOCK)
{
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock send error %s (%d). (%s)", WSErrorStr(iError), iError, pSock->m_sAddress);
#else
if (iBytes == -1)
{
if (errno != EAGAIN)
{
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] RegSock send error %s (%d). (%s)", ErrnoStr(errno), errno, pSock->m_sAddress);
#endif
if (iMsgLen > 0)
{
EventQueue::m_Ptr->AddThread(EventQueue::EVENT_REGSOCK_MSG, m_sMsg);
}
return false;
}
else
{
return true;
}
}
m_ui32BytesSent += iBytes;
if (iBytes < iLen)
{
pSock->m_pSendBufHead += iBytes;
return true;
}
else
{
int iMsgLen = snprintf(m_sMsg, 2048, "[REG] Hub is registered on %s hublist (Users: %u, Share: %" PRIu64 ")", pSock->m_sAddress, ServerManager::m_ui32Logged, ServerManager::m_ui64TotalShare);
if (iMsgLen > 0)
{
EventQueue::m_Ptr->AddThread(EventQueue::EVENT_REGSOCK_MSG, m_sMsg);
}
// Here is only one send, and when is all send then is time to delete this sock... false do it for us ;)
return false;
}
}
//---------------------------------------------------------------------------
void RegisterThread::RemoveSock(RegSocket * pSock)
{
if (pSock->m_pPrev == NULL)
{
if (pSock->m_pNext == NULL)
{
m_pRegSockListS = NULL;
m_pRegSockListE = NULL;
}
else
{
pSock->m_pNext->m_pPrev = NULL;
m_pRegSockListS = pSock->m_pNext;
}
}
else if (pSock->m_pNext == NULL)
{
pSock->m_pPrev->m_pNext = NULL;
m_pRegSockListE = pSock->m_pPrev;
}
else
{
pSock->m_pPrev->m_pNext = pSock->m_pNext;
pSock->m_pNext->m_pPrev = pSock->m_pPrev;
}
}
#endif // FLYLINKDC_REMOVE_REGISTER_THREAD
//---------------------------------------------------------------------------
↑ V1042 This file is marked with copyleft license, which requires you to open the derived source code.