222 lines
4.0 KiB
C++
222 lines
4.0 KiB
C++
/*
|
|
* This file is a part of Winix
|
|
* and is not publicly distributed
|
|
*
|
|
* Copyright (c) 2012, Tomasz Sowa
|
|
* All rights reserved.
|
|
*
|
|
*/
|
|
|
|
#include <algorithm>
|
|
#include "ipbancontainer.h"
|
|
#include "log.h"
|
|
#include "date/date.h"
|
|
|
|
|
|
|
|
IPBanContainer::IPBanContainer()
|
|
{
|
|
is_ipban_tab_sorted = true; // an empty list is sorted
|
|
soft_max_size = 100;
|
|
max_size = 110;
|
|
}
|
|
|
|
|
|
void IPBanContainer::SetMaxSize(size_t soft_size, size_t size)
|
|
{
|
|
soft_max_size = soft_size;
|
|
max_size = size;
|
|
|
|
if( max_size < soft_max_size )
|
|
max_size = soft_max_size + 1;
|
|
|
|
ipban_tab.reserve(max_size);
|
|
sort_helper_tab.reserve(max_size);
|
|
}
|
|
|
|
|
|
// returning a reference to the added (or existed) record
|
|
IPBan & IPBanContainer::AddIP(int ip)
|
|
{
|
|
IPBan * old_ip_ban = FindIP(ip);
|
|
|
|
if( !old_ip_ban )
|
|
{
|
|
IPBan ip_ban;
|
|
ip_ban.ip = ip;
|
|
|
|
if( ipban_tab.size() >= max_size )
|
|
RemoveOldRecords();
|
|
|
|
ipban_tab.push_back(ip_ban);
|
|
is_ipban_tab_sorted = false;
|
|
return ipban_tab.back();
|
|
}
|
|
else
|
|
{
|
|
return *old_ip_ban;
|
|
}
|
|
}
|
|
|
|
|
|
void IPBanContainer::RemoveIP(int ip)
|
|
{
|
|
IPBan * ipban = FindIP(ip);
|
|
|
|
if( ipban )
|
|
{
|
|
size_t index = ipban - &ipban_tab[0];
|
|
ipban_tab.erase(ipban_tab.begin() + index);
|
|
}
|
|
}
|
|
|
|
|
|
bool IPBanContainer::IsSorted()
|
|
{
|
|
return is_ipban_tab_sorted;
|
|
}
|
|
|
|
|
|
void IPBanContainer::Clear()
|
|
{
|
|
ipban_tab.clear();
|
|
is_ipban_tab_sorted = true;
|
|
}
|
|
|
|
|
|
// we need to remove some old records for the size of the container
|
|
// to be less or equal to soft_max_size
|
|
void IPBanContainer::RemoveOldRecords()
|
|
{
|
|
size_t to_remove = 0;
|
|
|
|
if( ipban_tab.size() >= soft_max_size )
|
|
to_remove = ipban_tab.size() - soft_max_size;
|
|
|
|
if( to_remove > 0 )
|
|
{
|
|
sort_helper_tab.resize(ipban_tab.size());
|
|
|
|
for(size_t i=0 ; i<ipban_tab.size() ; ++i)
|
|
sort_helper_tab[i] = i;
|
|
|
|
std::sort(sort_helper_tab.begin(), sort_helper_tab.end(), SortByLastUsedHelper(this));
|
|
sort_helper_tab.resize(to_remove);
|
|
std::sort(sort_helper_tab.begin(), sort_helper_tab.end());
|
|
|
|
while( to_remove-- > 0 )
|
|
ipban_tab.erase(ipban_tab.begin() + sort_helper_tab[to_remove]);
|
|
}
|
|
}
|
|
|
|
|
|
// for debug purposes
|
|
void IPBanContainer::PrintTab()
|
|
{
|
|
log << log4 << "ipban_tab (size: " << ipban_tab.size() << ")" << logend;
|
|
|
|
for(size_t i=0 ; i<ipban_tab.size() ; ++i)
|
|
{
|
|
log << log4 << i << ": ip: " << ipban_tab[i].ip << ", flags: " << ipban_tab[i].flags << ", last_used: ";
|
|
|
|
PT::Date date(ipban_tab[i].last_used);
|
|
log << date << ", expires: ";
|
|
|
|
date = ipban_tab[i].expires;
|
|
log << date << logend;
|
|
}
|
|
}
|
|
|
|
|
|
// for debug purposes
|
|
void IPBanContainer::PrintTab2()
|
|
{
|
|
log << log4 << "sort_helper_tab (size: " << sort_helper_tab.size() << ")" << logend;
|
|
|
|
for(size_t i=0 ; i<sort_helper_tab.size() ; ++i)
|
|
{
|
|
IPBan & ipban = ipban_tab[sort_helper_tab[i]];
|
|
|
|
log << log4 << i << ": ip: " << ipban.ip << ", flags: " << ipban.flags << ", last_used: ";
|
|
|
|
PT::Date date(ipban.last_used);
|
|
log << date << ", expires: ";
|
|
|
|
date = ipban.expires;
|
|
log << date << logend;
|
|
}
|
|
}
|
|
|
|
|
|
bool IPBanContainer::SortByLastUsedHelper::operator()(size_t index1, size_t index2)
|
|
{
|
|
if( index1 < container->ipban_tab.size() &&
|
|
index2 < container->ipban_tab.size() )
|
|
{
|
|
IPBan & ip1 = container->ipban_tab[index1];
|
|
IPBan & ip2 = container->ipban_tab[index2];
|
|
|
|
// prefer to select records which do not have WINIX_IPBAN_FLAG_ACTIVE
|
|
if( ip1.HasFlag(WINIX_IPBAN_FLAG_ACTIVE) !=
|
|
ip2.HasFlag(WINIX_IPBAN_FLAG_ACTIVE) )
|
|
{
|
|
return ip2.HasFlag(WINIX_IPBAN_FLAG_ACTIVE);
|
|
}
|
|
|
|
return ip1.last_used < ip2.last_used;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
IPBan * IPBanContainer::FindIP(int ip)
|
|
{
|
|
// !! IMPROVE ME add binary search if is_ipban_tab_sorted is true
|
|
|
|
for(size_t i=0 ; i<ipban_tab.size() ; ++i)
|
|
{
|
|
if( ipban_tab[i].ip == ip )
|
|
{
|
|
return &ipban_tab[i];
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
IPBan & IPBanContainer::GetIPBan(size_t index)
|
|
{
|
|
return ipban_tab[index];
|
|
}
|
|
|
|
|
|
void IPBanContainer::Sort()
|
|
{
|
|
std::sort(ipban_tab.begin(), ipban_tab.end(), SortIPBansFunction);
|
|
is_ipban_tab_sorted = true;
|
|
}
|
|
|
|
|
|
|
|
size_t IPBanContainer::Size()
|
|
{
|
|
return ipban_tab.size();
|
|
}
|
|
|
|
|
|
|
|
bool IPBanContainer::SortIPBansFunction(const IPBan & ip1, const IPBan & ip2)
|
|
{
|
|
return ip1.ip < ip2.ip;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|