254 lines
5.4 KiB
C++
254 lines
5.4 KiB
C++
/*
|
|
* This file is a part of Winix
|
|
* and is distributed under the 2-Clause BSD licence.
|
|
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 2012-2014, Tomasz Sowa
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
*/
|
|
|
|
#include <algorithm>
|
|
#include "ipbancontainer.h"
|
|
#include "log.h"
|
|
#include "date/date.h"
|
|
|
|
|
|
namespace Winix
|
|
{
|
|
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Winix
|
|
|
|
|
|
|
|
|
|
|