/* * This file is a part of Winix * and is distributed under the 2-Clause BSD licence. * Author: Tomasz Sowa */ /* * 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 #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 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 ; iipban_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