/*
* 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 "hashUsrManager.h"
//---------------------------------------------------------------------------
#include "User.h"
#include "utility.h"
//---------------------------------------------------------------------------
#ifdef _WIN32
#pragma hdrstop
#endif
//---------------------------------------------------------------------------
HashManager * HashManager::m_Ptr = nullptr;
//---------------------------------------------------------------------------
HashManager::HashManager()
{
memset(m_pIpTable, 0, sizeof(m_pIpTable));
//Memo("HashManager created");
}
//---------------------------------------------------------------------------
HashManager::~HashManager()
{
//Memo("HashManager destroyed");
for (uint32_t ui32i = 0; ui32i < 65536; ui32i++)
{
IpTableItem * cur = NULL,
* next = m_pIpTable[ui32i];
while (next != NULL)
{
cur = next;
next = cur->m_pNext;
delete cur;
}
}
}
//---------------------------------------------------------------------------
bool HashManager::Add(User * pUser)
{
if (pUser->m_sNick)
{
m_NickTable[std::string(pUser->m_sNick, pUser->m_ui8NickLen)] = pUser;
}
if (m_pIpTable[pUser->m_ui16IpTableIdx] == NULL)
{
m_pIpTable[pUser->m_ui16IpTableIdx] = new (std::nothrow) IpTableItem;
if (m_pIpTable[pUser->m_ui16IpTableIdx] == NULL)
{
pUser->m_ui32BoolBits |= User::BIT_ERROR;
pUser->Close();
AppendDebugLog("%s - [MEM] Cannot allocate IpTableItem in HashManager::Add\n");
return false;
}
m_pIpTable[pUser->m_ui16IpTableIdx]->m_pNext = nullptr;
m_pIpTable[pUser->m_ui16IpTableIdx]->m_pPrev = nullptr;
m_pIpTable[pUser->m_ui16IpTableIdx]->m_pFirstUser = pUser;
m_pIpTable[pUser->m_ui16IpTableIdx]->m_ui16Count = 1;
return true;
}
IpTableItem * cur = NULL,
* next = m_pIpTable[pUser->m_ui16IpTableIdx];
while (next != NULL)
{
cur = next;
next = cur->m_pNext;
if (memcmp(cur->m_pFirstUser->m_ui128IpHash, pUser->m_ui128IpHash, 16) == 0)
{
cur->m_pFirstUser->m_pHashIpTablePrev = pUser;
pUser->m_pHashIpTableNext = cur->m_pFirstUser;
cur->m_pFirstUser = pUser;
cur->m_ui16Count++;
return true;
}
}
cur = new (std::nothrow) IpTableItem;
if (cur == NULL)
{
pUser->m_ui32BoolBits |= User::BIT_ERROR;
pUser->Close();
AppendDebugLog("%s - [MEM] Cannot allocate IpTableItem2 in HashManager::Add\n");
return false;
}
cur->m_pFirstUser = pUser;
cur->m_ui16Count = 1;
cur->m_pNext = m_pIpTable[pUser->m_ui16IpTableIdx];
cur->m_pPrev = nullptr;
m_pIpTable[pUser->m_ui16IpTableIdx]->m_pPrev = cur;
m_pIpTable[pUser->m_ui16IpTableIdx] = cur;
return true;
}
//---------------------------------------------------------------------------
void HashManager::Remove(User * pUser)
{
if (pUser->m_sNick)
{
m_NickTable.erase(std::string(pUser->m_sNick, pUser->m_ui8NickLen));
}
if (pUser->m_pHashIpTablePrev == NULL)
{
IpTableItem * cur = NULL,
* next = m_pIpTable[pUser->m_ui16IpTableIdx];
while (next != NULL)
{
cur = next;
next = cur->m_pNext;
if (memcmp(cur->m_pFirstUser->m_ui128IpHash, pUser->m_ui128IpHash, 16) == 0)
{
cur->m_ui16Count--;
if (pUser->m_pHashIpTableNext == NULL)
{
if (cur->m_pPrev == NULL)
{
if (cur->m_pNext == NULL)
{
m_pIpTable[pUser->m_ui16IpTableIdx] = nullptr;
}
else
{
cur->m_pNext->m_pPrev = nullptr;
m_pIpTable[pUser->m_ui16IpTableIdx] = cur->m_pNext;
}
}
else if (cur->m_pNext == NULL)
{
cur->m_pPrev->m_pNext = nullptr;
}
else
{
cur->m_pPrev->m_pNext = cur->m_pNext;
cur->m_pNext->m_pPrev = cur->m_pPrev;
}
delete cur;
}
else
{
pUser->m_pHashIpTableNext->m_pHashIpTablePrev = nullptr;
cur->m_pFirstUser = pUser->m_pHashIpTableNext;
}
pUser->m_pHashIpTablePrev = nullptr;
pUser->m_pHashIpTableNext = nullptr;
return;
}
}
}
else if (pUser->m_pHashIpTableNext == NULL)
{
pUser->m_pHashIpTablePrev->m_pHashIpTableNext = nullptr;
}
else
{
pUser->m_pHashIpTablePrev->m_pHashIpTableNext = pUser->m_pHashIpTableNext;
pUser->m_pHashIpTableNext->m_pHashIpTablePrev = pUser->m_pHashIpTablePrev;
}
pUser->m_pHashIpTablePrev = nullptr;
pUser->m_pHashIpTableNext = nullptr;
IpTableItem * cur = NULL,
* next = m_pIpTable[pUser->m_ui16IpTableIdx];
while (next != NULL)
{
cur = next;
next = cur->m_pNext;
if (memcmp(cur->m_pFirstUser->m_ui128IpHash, pUser->m_ui128IpHash, 16) == 0)
{
cur->m_ui16Count--;
return;
}
}
}
//---------------------------------------------------------------------------
User * HashManager::FindUser(const std::string& sNick) const
{
auto i = m_NickTable.find(sNick);
if (i != m_NickTable.end())
{
return i->second;
}
return NULL;
}
//---------------------------------------------------------------------------
User * HashManager::FindUser(const char * sNick, const size_t szNickLen) const
{
if (sNick)
{
return FindUser(std::string(sNick, szNickLen));
}
// no equal hash found, we dont have the nick in list
return NULL;
}
//---------------------------------------------------------------------------
User * HashManager::FindUser(const User * pUser) const
{
return FindUser(pUser->m_sNick, pUser->m_ui8NickLen);
}
//---------------------------------------------------------------------------
User * HashManager::FindUser(const uint8_t * ui128IpHash) const
{
uint16_t ui16IpTableIdx = 0;
if (IN6_IS_ADDR_V4MAPPED((const in6_addr *)ui128IpHash))
{
ui16IpTableIdx = ui128IpHash[14] * ui128IpHash[15];
}
else
{
ui16IpTableIdx = GetIpTableIdx(ui128IpHash);
}
IpTableItem * cur = NULL,
* next = m_pIpTable[ui16IpTableIdx];
while (next != NULL)
{
cur = next;
next = cur->m_pNext;
if (memcmp(cur->m_pFirstUser->m_ui128IpHash, ui128IpHash, 16) == 0)
{
return cur->m_pFirstUser;
}
}
return NULL;
}
//---------------------------------------------------------------------------
uint32_t HashManager::GetUserIpCount(const User * pUser) const
{
IpTableItem * cur = NULL,
* next = m_pIpTable[pUser->m_ui16IpTableIdx];
while (next != NULL)
{
cur = next;
next = cur->m_pNext;
if (memcmp(cur->m_pFirstUser->m_ui128IpHash, pUser->m_ui128IpHash, 16) == 0)
{
return cur->m_ui16Count;
}
}
return 0;
}
//---------------------------------------------------------------------------
↑ V1042 This file is marked with copyleft license, which requires you to open the derived source code.