diff options
Diffstat (limited to 'rtorrent-extended/ip_filter_no_boost_fast.patch')
-rw-r--r-- | rtorrent-extended/ip_filter_no_boost_fast.patch | 1083 |
1 files changed, 1083 insertions, 0 deletions
diff --git a/rtorrent-extended/ip_filter_no_boost_fast.patch b/rtorrent-extended/ip_filter_no_boost_fast.patch new file mode 100644 index 0000000..d13fb69 --- /dev/null +++ b/rtorrent-extended/ip_filter_no_boost_fast.patch @@ -0,0 +1,1083 @@ +diff --git a/src/command_network.cc b/src/command_network.cc +index 34f75ab..2494988 100644 +--- a/src/command_network.cc ++++ b/src/command_network.cc +@@ -36,6 +36,11 @@ + + #include "config.h" + ++#include <string> ++#include <sstream> ++#include <list> ++#include <unistd.h> ++ + #include <functional> + #include <cstdio> + #include <rak/address_info.h> +@@ -62,6 +67,10 @@ + #include "control.h" + #include "command_helpers.h" + ++#include "utils/pattern.h" ++#include "core/ip_filter.h" ++ ++ + torrent::Object + apply_throttle(bool up, const torrent::Object& rawArgs) { + const torrent::Object::list_type& args = rawArgs.as_list(); +@@ -209,6 +218,59 @@ apply_encryption(const torrent::Object& rawArgs) { + } + + torrent::Object ++apply_ip_filter(const torrent::Object& rawArgs) { ++ const torrent::Object::list_type& args = rawArgs.as_list(); ++ ++ std::list<std::string> files; ++ ++ for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) { ++ std::string file( itr->as_string() ); ++ utils::trim( file ); ++ if( access(file.c_str(),F_OK | R_OK) ) ++ throw torrent::input_error("IpFilter file '" + file + "' does not exist or not readable. Filter could not be loaded"); ++ files.push_back( file ); ++ } ++ ++ std::stringstream logMsg; ++ if( files.empty() ) { ++ logMsg << "IpFilter is empty"; ++ control->core()->push_log( logMsg.str().c_str() ); ++ } ++ else { ++ core::IpFilter* f = new core::IpFilter(); ++ logMsg << "IpFilter is initialized with files: "; ++ int entries = 0; ++ clock_t time_start = clock(); ++ for( std::list<std::string>::iterator itr = files.begin(); itr != files.end(); itr++) { ++ std::cout << "Loading IP filters from '" << *itr << "'..."; ++ std::cout.flush(); ++ if( itr != files.begin() ) ++ logMsg << ", "; ++ logMsg << *itr; ++ int merges = f->add_from_file( *itr ); ++ if( merges < 0 ) { ++ std::cout << "error" << std::endl; ++ std::cout.flush(); ++ throw torrent::input_error("IpFilter could not load file '" + *itr + "'"); ++ } ++ std::cout << "done. Loaded " << (f->size()-entries) << " ranges. " << merges << " ranges were merged." << std::endl; ++ std::cout.flush(); ++ entries = f->size(); ++ } ++ control->core()->push_log( logMsg.str().c_str() ); ++ std::stringstream logMsg2("IpFilter loaded with "); ++ logMsg2 << f->size() << " ranges total. " << f->get_merges() << " ranges were merged."; ++ control->core()->push_log( logMsg2.str().c_str() ); ++ std::cout << logMsg2.str() << std::endl; ++ std::cout << "IP_Filters loaded in " << (double)(clock()-time_start)/CLOCKS_PER_SEC << " seconds" << std::endl; ++ std::cout.flush(); ++ control->core()->set_ip_filter( f ); ++ } ++ ++ return torrent::Object(); ++} ++ ++torrent::Object + apply_tos(const torrent::Object& rawArg) { + rpc::Command::value_type value; + torrent::ConnectionManager* cm = torrent::connection_manager(); +@@ -492,6 +554,9 @@ initialize_command_network() { + + ADD_VARIABLE_BOOL("peer_exchange", true); + ++ ADD_COMMAND_VOID("reload_ip_filter", rak::make_mem_fun(control->core(), &core::Manager::reload_ip_filter)); ++ ADD_COMMAND_LIST("ip_filter", rak::ptr_fn(&apply_ip_filter)); ++ + // Not really network stuff: + ADD_VARIABLE_BOOL ("handshake_log", false); + ADD_VARIABLE_STRING("log.tracker", ""); +diff --git a/src/core/Makefile.am b/src/core/Makefile.am +index fe07cbf..fb26380 100644 +--- a/src/core/Makefile.am ++++ b/src/core/Makefile.am +@@ -36,6 +36,15 @@ libsub_core_a_SOURCES = \ + view.cc \ + view.h \ + view_manager.cc \ +- view_manager.h ++ view_manager.h \ ++ ip_address.cc \ ++ ip_address.h \ ++ ip_filter.cc \ ++ ip_filter.h \ ++ ip_range.cc \ ++ ip_range.h \ ++ printable.h \ ++ regex_namespace.h \ ++ ip_filter_statics.cc + + INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir) +diff --git a/src/core/Makefile.in b/src/core/Makefile.in +index 24b7eb4..32b0f6b 100644 +--- a/src/core/Makefile.in ++++ b/src/core/Makefile.in +@@ -63,7 +63,11 @@ am_libsub_core_a_OBJECTS = curl_get.$(OBJEXT) curl_socket.$(OBJEXT) \ + manager.$(OBJEXT) poll_manager.$(OBJEXT) \ + poll_manager_epoll.$(OBJEXT) poll_manager_kqueue.$(OBJEXT) \ + poll_manager_select.$(OBJEXT) view.$(OBJEXT) \ +- view_manager.$(OBJEXT) ++ view_manager.$(OBJEXT) \ ++ ip_address.$(OBJEXT) \ ++ ip_filter.$(OBJEXT) \ ++ ip_range.$(OBJEXT) \ ++ ip_filter_statics.$(OBJEXT) + libsub_core_a_OBJECTS = $(am_libsub_core_a_OBJECTS) + DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) + depcomp = $(SHELL) $(top_srcdir)/depcomp +@@ -252,7 +256,16 @@ libsub_core_a_SOURCES = \ + view.cc \ + view.h \ + view_manager.cc \ +- view_manager.h ++ view_manager.h \ ++ ip_address.cc \ ++ ip_address.h \ ++ ip_filter.cc \ ++ ip_filter.h \ ++ ip_range.cc \ ++ ip_range.h \ ++ printable.h \ ++ regex_namespace.h \ ++ ip_filter_statics.cc + + INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir) + all: all-am +@@ -320,6 +333,9 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/poll_manager_select.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/view.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/view_manager.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ip_address.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ip_range.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ip_filter_statics.Po@am__quote@ + + .cc.o: + @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +diff --git a/src/core/ip_address.cc b/src/core/ip_address.cc +new file mode 100644 +index 0000000..a9a9251 +--- /dev/null ++++ b/src/core/ip_address.cc +@@ -0,0 +1,25 @@ ++#include <cstdlib> ++#include <string> ++#include <arpa/inet.h> ++ ++#include "ip_address.h" ++#include "utils/pattern.h" ++ ++namespace core { ++ ++std::pair<bool,uint32_t> IpAddress::to_int( const std::string& address ) { ++ uint32_t a; ++ int r = inet_pton( AF_INET, address.c_str(), &a); ++ if( r ) ++ a = ntohl( a ); ++ return std::pair<bool,uint32_t>( (r!=0), a ); ++} ++ ++std::string IpAddress::to_string() const { ++ char buf[128] = ""; ++ uint32_t a = htonl( m_address ); ++ inet_ntop( AF_INET, &a, buf, sizeof(buf) ); ++ return std::string( buf ); ++} ++ ++} +diff --git a/src/core/ip_address.h b/src/core/ip_address.h +new file mode 100644 +index 0000000..a9ad142 +--- /dev/null ++++ b/src/core/ip_address.h +@@ -0,0 +1,65 @@ ++#ifndef IPADDRESS_H ++#define IPADDRESS_H ++ ++#include <inttypes.h> ++#include <string> ++ ++#include "printable.h" ++#include "utils/pattern.h" ++#include "regex_namespace.h" ++ ++namespace core { ++ ++class IpAddress : public Printable { ++ friend class IpRange; ++ ++ private: // constants ++ static const std::string PATTERN_IP_EXPRESSION; ++ static const std::string PATTERN_IP_BYTES_EXPRESSION; ++ static const regex::Pattern PATTERN_IP_BYTES; ++ ++ static const int GRP_IP_FIRST_BYTE; ++ static const int GRP_IP_BYTES_COUNT; ++ ++ private: // fields ++ uint32_t m_address; ++ ++ private: // static methods ++ ++ private: // dynamic methods ++ IpAddress() : m_address(0) {} ++ ++ void copy( const IpAddress& addr ) { m_address = addr.m_address;} ++ ++ public: // static methods ++ static std::pair<bool,uint32_t> to_int( const std::string& strAddress ); ++ static IpAddress* parse( const std::string& strAddress ) { ++ std::pair<bool,uint32_t> result = to_int( strAddress ); ++ return ( !result.first ) ? NULL : new IpAddress( result.second ); ++ } ++ ++ public: // dynamic methods ++ IpAddress( uint32_t address ) : m_address(address) {} ++ IpAddress( const IpAddress& addr ) { copy( addr ); } ++ IpAddress& operator= ( const IpAddress& addr ) { copy( addr ); return *this; } ++ ++ operator uint32_t() const { return m_address; } ++ ++ bool operator>= ( const IpAddress& ip ) const { return (m_address >= ip.m_address); } ++ bool operator<= ( const IpAddress& ip ) const { return (m_address <= ip.m_address); } ++ bool operator< ( const IpAddress& ip ) const { return (m_address < ip.m_address); } ++ bool operator> ( const IpAddress& ip ) const { return (m_address > ip.m_address); } ++ bool operator== ( const IpAddress& ip ) const { return (m_address == ip.m_address); } ++ bool operator!= ( const IpAddress& ip ) const { return (m_address != ip.m_address); } ++ ++ bool operator>= ( uint32_t ip ) const { return (m_address >= ip); } ++ bool operator<= ( uint32_t ip ) const { return (m_address <= ip); } ++ bool operator< ( uint32_t ip ) const { return (m_address < ip); } ++ bool operator> ( uint32_t ip ) const { return (m_address > ip); } ++ bool operator== ( uint32_t ip ) const { return (m_address == ip); } ++ bool operator!= ( uint32_t ip ) const { return (m_address != ip); } ++ ++ std::string to_string() const; ++ }; ++} ++#endif +diff --git a/src/core/ip_filter.cc b/src/core/ip_filter.cc +new file mode 100644 +index 0000000..8f46a42 +--- /dev/null ++++ b/src/core/ip_filter.cc +@@ -0,0 +1,165 @@ ++#include <sstream> ++#include <string> ++#include <map> ++#include <list> ++#include <fstream> ++#include <stdio.h> ++#include <stdlib.h> ++ ++#include "ip_filter.h" ++ ++namespace core { ++ ++int IpFilter::merge_and_insert( range_map* rs, IpRange* r ) { ++ if( !r || !r->get_from() ) ++ return 0; ++ ++ std::pair<const IpAddress,IpRange::ptr> p( *r->get_from(), IpRange::ptr(r) ); ++ std::pair<range_itr,bool> duo = rs->insert( p ); ++ ++ range_itr idx = duo.first; ++ bool wasInserted = duo.second; ++ IpRange* curr = NULL; ++ int mergeCount = 0; ++ ++ if( !wasInserted ) { // exactly the same start address already exists ++ curr = idx->second; ++ if( *curr->get_to() < *r->get_to() ) ++ curr->set_to( r->get_to() ); ++ delete r; ++ r = curr; ++ mergeCount++; ++ } ++ else { ++ if( idx != rs->begin() ) { ++ --idx; ++ curr = idx->second; // previous ++ if( *r->get_from() <= *curr->get_to() ) ++ r = curr; ++ else ++ ++idx; ++ } ++ } ++ ++ if( idx != rs->end() ) ++ ++idx; ++ ++ while( idx != rs->end() ) { ++ curr = idx->second; ++ if( *r->get_to() < *curr->get_from() ) ++ break; ++ ++ std::string d = r->get_description(); ++ d += " / " + curr->get_description(); ++ r->set_description( d ); ++ if( *r->get_to() < *curr->get_to() ) ++ r->set_to( curr->get_to() ); ++ rs->erase( idx++ ); ++ delete curr; ++ mergeCount++; ++ } ++ return mergeCount; ++} ++ ++int IpFilter::add_from_file( const std::string& fileName, range_map* rs, str_list* files ) { ++ FILE *f = fopen(fileName.c_str(),"r"); ++ int mergeCount = 0; ++ if (f==0) return -1; ++ char *line = (char *)malloc(64); ++ size_t sz=64; ++ int charsread = 0; ++ int linesread=0; ++ while( (charsread=getline(&line,&sz,f)) >=0 ) { ++ if( (line[0] == '#' ) || ( charsread <= 1 ) ) ++ continue; ++ ++ IpRange* ir = IpRange::parse( line, charsread ); ++ if( !ir || !ir->get_from() || !ir->get_to() ) ++ continue; ++ ++ mergeCount += merge_and_insert( rs, ir ); ++ } ++ free(line); ++ files->push_back( std::string(fileName) ); ++ fclose(f); ++ m_merges += mergeCount; ++ return mergeCount; ++} ++ ++int IpFilter::add_from_file( const std::string& fileName ) { ++ if( !m_ranges ) ++ m_ranges = new range_map(); ++ if( !m_loadedFiles ) ++ m_loadedFiles = new std::list<std::string>(); ++ ++ return add_from_file( fileName, m_ranges, m_loadedFiles ); ++} ++ ++int IpFilter::reload() { ++ if( !m_loadedFiles || m_loadedFiles->empty() ) ++ return 0; ++ ++ range_map* rs = new range_map(); ++ str_list* files = new str_list(); ++ int mergeCount = 0; ++ for( str_list::const_iterator it = m_loadedFiles->begin(), end = m_loadedFiles->end(); it != end; it++ ) ++ mergeCount += add_from_file( *it, rs, files ); ++ ++ range_map* rsOld = m_ranges; ++ m_ranges = rs; ++ if( rsOld ) { ++ clear( rsOld ); ++ delete rsOld; ++ } ++ ++ str_list* filesOld = m_loadedFiles; ++ m_loadedFiles = files; ++ if( filesOld ) { ++ clear( filesOld ); ++ delete filesOld; ++ } ++ ++ m_merges = mergeCount; ++ return mergeCount; ++} ++ ++IpRange* IpFilter::find_range( uint32_t ip ) const { ++ if( (ip >= 0) && m_ranges && !m_ranges->empty() ) { ++ range_itr idx = m_ranges->upper_bound( ip ); ++ if( idx != m_ranges->begin() ) ++ --idx; ++ IpRange* curr = idx->second; ++ if( curr->includes( ip ) ) ++ return curr; ++ } ++ return NULL; ++} ++ ++std::string IpFilter::to_string() const { ++ std::stringstream result; ++ if( !m_ranges ) ++ result << "NULL" << std::endl; ++ else { ++ for( range_map::const_iterator it = m_ranges->begin() ; it != m_ranges->end(); it++ ) { ++ const IpAddress a = it->first; ++ IpRange* ir = it->second; ++ result << a << ": " << *ir << std::endl; ++ } ++ } ++ return result.str(); ++} ++ ++void IpFilter::clear( range_map* map ) { ++ if( map ) { ++ for( range_itr i = map->begin(), j = map->end(); i != j; i++ ) ++ delete i->second; ++ map->clear(); ++ } ++} ++ ++void IpFilter::clear( str_list* list ) { ++ if( list ) ++ list->clear(); ++} ++ ++} +diff --git a/src/core/ip_filter.h b/src/core/ip_filter.h +new file mode 100644 +index 0000000..07f2004 +--- /dev/null ++++ b/src/core/ip_filter.h +@@ -0,0 +1,85 @@ ++#ifndef IPFILTER_H ++#define IPFILTER_H ++ ++#include <string> ++#include <map> ++#include <list> ++ ++#include "printable.h" ++#include "ip_address.h" ++#include "ip_range.h" ++ ++namespace core { ++ ++typedef std::map<const IpAddress,IpRange::ptr> range_map; ++typedef range_map::iterator range_itr; ++typedef std::list<std::string> str_list; ++ ++class IpFilter : public Printable { ++ private: // fields ++ int m_merges; ++ range_map* m_ranges; ++ str_list* m_loadedFiles; ++ ++ private: // static methods ++ static void clear( range_map* map ); ++ static void clear( str_list* list ); ++ ++ private: // dynamic methods ++ void init_members(void) { // to avoid long constructor lines for every ctor ++ m_ranges = NULL; ++ m_loadedFiles = NULL; ++ m_merges = 0; ++ } ++ int merge_and_insert( range_map* rs, IpRange* r ); ++ int add_from_file( const std::string& fileName, range_map* rs, str_list* files ); ++ ++ public: // static methods ++ ++ public: // dynamic methods ++ IpFilter() { init_members(); } ++ ~IpFilter() { ++ clear(); ++ if( m_ranges ) delete m_ranges; ++ if( m_loadedFiles ) delete m_loadedFiles; ++ m_ranges = NULL; ++ m_loadedFiles = NULL; ++ } ++ IpFilter( std::string* files, int size ) { ++ init_members(); ++ for( int i = 0; i < size; i++, files++ ) ++ add_from_file( *files ); ++ } ++ IpFilter( str_list& files ) { ++ init_members(); ++ for( str_list::const_iterator i = files.begin(), last = files.end(); i != last; i++ ) ++ add_from_file( *i ); ++ } ++ IpFilter( IpFilter& f ) { ++ init_members(); ++ m_ranges = new range_map( *f.m_ranges ); ++ m_loadedFiles = new str_list( *f.m_loadedFiles ); ++ } ++ ++ int reload(); ++ int add_from_file( const std::string& fileName ); ++ int add_from_file( char* fileName ) { std::string s( fileName ); return add_from_file(s); } ++ void clear() { clear( m_ranges ); clear( m_loadedFiles ); } ++ ++ IpRange* find_range( uint32_t ip ) const; ++ ++ bool is_filtered( uint32_t ip ) const { return (find_range( ip ) != NULL); } ++ bool is_filtered( std::string ip ) const { ++ static std::pair<bool,uint32_t> ipInt = IpAddress::to_int( ip ); ++ return (!ipInt.first ? false : is_filtered( ipInt.second )); ++ } ++ ++ std::string to_string() const; ++ ++ int size(void) { return ( m_ranges ? m_ranges->size() : 0 ); } ++ int get_merges(void) { return m_merges; } ++ void set_files( str_list& files) { m_loadedFiles = new str_list( files ); } ++}; ++ ++} ++#endif +diff --git a/src/core/ip_filter_statics.cc b/src/core/ip_filter_statics.cc +new file mode 100644 +index 0000000..042377d +--- /dev/null ++++ b/src/core/ip_filter_statics.cc +@@ -0,0 +1,21 @@ ++#include "ip_address.h" ++#include "ip_range.h" ++#include "utils/pattern.h" ++ ++namespace core { ++ ++const std::string IpAddress::PATTERN_IP_EXPRESSION = "(([0-9]{1,3}\\.){3}[0-9]{1,3})"; ++const std::string IpAddress::PATTERN_IP_BYTES_EXPRESSION = "([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})"; ++const regex::Pattern IpAddress::PATTERN_IP_BYTES = PATTERN_IP_BYTES_EXPRESSION; ++ ++const int IpAddress::GRP_IP_FIRST_BYTE = 1; ++const int IpAddress::GRP_IP_BYTES_COUNT = 4; ++ ++const std::string IpRange::PATTERN_RANGE_EXPRESSION = "[[:space:]]*(.*)[[:space:]]*:[[:space:]]*" + IpAddress::PATTERN_IP_EXPRESSION + "[[:space:]]*-[[:space:]]*" + IpAddress::PATTERN_IP_EXPRESSION + "[[:space:]]*"; ++const regex::Pattern IpRange::PATTERN_RANGE = PATTERN_RANGE_EXPRESSION; ++ ++const int IpRange::GRP_DESCRIPTION = 1; ++const int IpRange::GRP_FIRST_IP = 2; ++const int IpRange::GRP_SECOND_IP = 4; ++ ++} +diff --git a/src/core/ip_range.cc b/src/core/ip_range.cc +new file mode 100644 +index 0000000..3923e53 +--- /dev/null ++++ b/src/core/ip_range.cc +@@ -0,0 +1,112 @@ ++#include <sstream> ++#include <string> ++ ++#include "ip_range.h" ++#include "utils/pattern.h" ++#include "regex_namespace.h" ++ ++namespace core { ++ ++IpRange* IpRange::parse( const std::string& s ) { ++ regex::Match m = PATTERN_RANGE.match( s ); ++ ++ if( !m.matches() ) { ++ std::cout << "!! range format is invalid: '" << s << "'" << std::endl; ++ return NULL; ++ } ++ ++ std::string description = m.group( GRP_DESCRIPTION ); ++ std::string ip1 = m.group( GRP_FIRST_IP ); ++ std::string ip2 = m.group( GRP_SECOND_IP ); ++ IpAddress* from = IpAddress::parse( ip1 ); ++ IpAddress* to = IpAddress::parse( ip2 ); ++ ++ if( !from ) { ++ std::cout << "!! from is invalid: description='" << description << ", ip1=" << ip1 << ", ip2=" << ip2 << std::endl; ++ return NULL; ++ } ++ if( !to ) { ++ std::cout << "!! to is invalid: description='" << description << ", ip1=" << ip1 << ", ip2=" << ip2 << std::endl; ++ return NULL; ++ } ++ ++// if( !from || !to || (*to < *from) ) ++// return NULL; ++ ++ IpRange* r = new IpRange(); ++ ++ r->m_description = description; ++ r->m_from = from; ++ r->m_to = to; ++ ++ if( to && from && (*to < *from) ) { ++ std::cout << "!! to < from: " << r->to_string() << std::endl; ++ delete r; ++ return NULL; ++ } ++ ++ return r; ++} ++ ++//fast version ++IpRange* IpRange::parse( const char *s, const int size ){ ++ static char description[256]; ++ static char ip1[24], ip2[24]; ++ int pos=0, post=0, enddesc=size-1; ++ while (enddesc>0 && s[enddesc]!=':') enddesc--; //find last ':' in the line ++ while((pos<enddesc) && (unsigned char)s[pos]<=' ') pos++; // strip from start ++ while ((pos<enddesc)){ ++ if (post<255) description[post++]=s[pos]; ++ pos++; ++ } ++ description[post]=0; ++ if (s[pos]==':') pos++; ++ post=0; ++ while ((pos<size) && s[pos]!='-'){ ++ if (post<23) ip1[post++]=s[pos]; ++ pos++; ++ } ++ ip1[post]=0; ++ if (s[pos]=='-'){ ++ pos++; ++ post=0; ++ while ((pos<size) && s[pos]>' '){ ++ if (post<23) ip2[post++]=s[pos]; ++ pos++; ++ } ++ ip2[post]=0; ++ } else ip2[0]=0; ++ ++ IpAddress* from = IpAddress::parse(ip1); ++ IpAddress* to = IpAddress::parse(ip2); ++ ++ if( !from ) { ++ std::cout << "!! from is invalid: description='" << description << ", ip1=" << ip1 << ", ip2=" << ip2 << std::endl; ++ return NULL; ++ } ++ if( !to ) { ++ std::cout << "!! to is invalid: description='" << description << ", ip1=" << ip1 << ", ip2=" << ip2 << std::endl; ++ return NULL; ++ } ++ ++ IpRange* r = new IpRange(); ++ r->m_description = description; ++ r->m_from = from; ++ r->m_to = to; ++ ++ if( (*to < *from) ) { ++ std::cout << "!! to < from: " << r->to_string() << std::endl; ++ delete r; ++ return NULL; ++ } ++ ++ return r; ++} ++ ++std::string IpRange::to_string() const { ++ std::stringstream result; ++ result << m_description << ": [" << m_from->to_string() << " - " << m_to->to_string() << ']'; ++ return result.str(); ++} ++ ++} +diff --git a/src/core/ip_range.h b/src/core/ip_range.h +new file mode 100644 +index 0000000..1fb2322 +--- /dev/null ++++ b/src/core/ip_range.h +@@ -0,0 +1,67 @@ ++#ifndef IPRANGE_H ++#define IPRANGE_H ++ ++#include <string> ++ ++#include "printable.h" ++#include "ip_address.h" ++#include "utils/pattern.h" ++#include "regex_namespace.h" ++ ++namespace core { ++ ++class IpRange : public Printable { ++ public: // constants ++ static const std::string PATTERN_RANGE_EXPRESSION; ++ static const regex::Pattern PATTERN_RANGE; ++ ++ static const int GRP_DESCRIPTION; ++ static const int GRP_FIRST_IP; ++ static const int GRP_SECOND_IP; ++ ++ private: // fields ++ std::string m_description; ++ const IpAddress* m_from; ++ const IpAddress* m_to; ++ ++ private: // dynamic methods ++ IpRange() : m_description(), m_from(NULL), m_to(NULL) {} ++ ++ public: // static methods ++ typedef IpRange* ptr; ++ static IpRange* parse( const std::string& s ); ++ static IpRange* parse( const char *s, const int size ); ++ ++ public: // dynamic methods ++ IpRange( IpRange& rng ) { copy(rng); } ++ IpRange& operator= ( IpRange& rng ) { copy(rng); return *this; } ++ ++ void copy( IpRange& rng ) { ++ m_description = rng.m_description; ++ m_from = (!rng.m_from) ? NULL : new IpAddress( *rng.m_from ); ++ m_to = (!rng.m_to) ? NULL : new IpAddress( *rng.m_to ); ++ } ++ ++ const std::string& get_description ( void ) const { return m_description; } ++ const IpAddress* get_from ( void ) const { return m_from; } ++ const IpAddress* get_to ( void ) const { return m_to; } ++ ++ void set_description ( const std::string& description ) { m_description = description; } ++ void set_from ( const IpAddress* from ) { if( m_from ) delete m_from; m_from = new IpAddress( *from ); } ++ void set_to ( const IpAddress* to ) { if( m_to ) delete m_to; m_to = new IpAddress( *to ); } ++ ++ bool includes( const IpAddress& ip ) const { return includes((uint32_t)ip); } ++ bool includes( uint32_t ip ) const { return (*m_from <= ip) && (*m_to >= ip); } ++ ++ ~IpRange() { ++ delete m_from; ++ m_from = NULL; ++ delete m_to; ++ m_to = NULL; ++ } ++ ++ std::string to_string() const; ++}; ++ ++} ++#endif +diff --git a/src/core/manager.cc b/src/core/manager.cc +index 2a422c8..9c1d004 100644 +--- a/src/core/manager.cc ++++ b/src/core/manager.cc +@@ -153,6 +153,24 @@ Manager::handshake_log(const sockaddr* sa, int msg, int err, const torrent::Hash + } + } + ++uint32_t ++Manager::filter_ip(const sockaddr* sa) { ++ IpRange* r = NULL; ++ // if something's wrong with filter or address it's gonna be allowed ++ if( m_ipFilter && sa ) { ++ const rak::socket_address* socketAddress = rak::socket_address::cast_from(sa); ++ if( socketAddress->is_valid() && (socketAddress->family() == rak::socket_address::af_inet) ) ++ r = m_ipFilter->find_range( socketAddress->sa_inet()->address_h() ); ++ if( r ) ++ m_logComplete.push_front("Address '" + socketAddress->address_str() + "' is rejected by IP filter range '" + r->to_string()); ++ else ++ if( rpc::call_command_value("get_handshake_log") ) ++ m_logComplete.push_front("IP Filter allowed connection with '" + socketAddress->address_str() + "'"); ++ } ++ return (r==NULL); ++} ++ ++ + void + Manager::push_log(const char* msg) { + m_logImportant.push_front(msg); +@@ -160,7 +178,8 @@ Manager::push_log(const char* msg) { + } + + Manager::Manager() : +- m_hashingView(NULL) ++ m_hashingView(NULL), ++ m_ipFilter(NULL) + // m_pollManager(NULL) { + { + m_downloadStore = new DownloadStore(); +@@ -181,6 +200,8 @@ Manager::~Manager() { + delete m_downloadStore; + delete m_httpQueue; + delete m_fileStatusCache; ++ ++ set_ip_filter( NULL ); + } + + void +@@ -226,6 +247,7 @@ Manager::initialize_second() { + CurlStack::global_init(); + + torrent::connection_manager()->set_signal_handshake_log(sigc::mem_fun(this, &Manager::handshake_log)); ++ torrent::connection_manager()->set_filter(sigc::mem_fun(this, &Manager::filter_ip)); + } + + void +@@ -585,4 +607,13 @@ Manager::receive_hashing_changed() { + } + } + ++void Manager::reload_ip_filter(void) { ++ if( m_ipFilter ) { ++ push_log("Reloading IP filter"); ++ m_ipFilter->reload(); ++ std::stringstream logMsg("IpFilter reloaded with "); ++ logMsg << m_ipFilter->size() << " ranges total. " << m_ipFilter->get_merges() << " ranges were merged."; ++ push_log( logMsg.str().c_str() ); ++} ++} + } +diff --git a/src/core/manager.h b/src/core/manager.h +index 16902af..ac01981 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -47,6 +47,8 @@ + #include "range_map.h" + #include "log.h" + ++#include "ip_filter.h" ++ + namespace torrent { + class Bencode; + } +@@ -118,6 +120,15 @@ public: + + void handshake_log(const sockaddr* sa, int msg, int err, const torrent::HashString* hash); + ++ uint32_t filter_ip(const sockaddr* sa); ++ ++ void set_ip_filter( IpFilter* ipFilter ) { ++ IpFilter* old = m_ipFilter; ++ m_ipFilter = ipFilter; ++ if( old ) delete old; ++ } ++ void reload_ip_filter(void); ++ + static const int create_start = 0x1; + static const int create_tied = 0x2; + static const int create_quiet = 0x4; +@@ -154,6 +165,8 @@ private: + + Log m_logImportant; + Log m_logComplete; ++ ++ IpFilter* m_ipFilter; + }; + + // Meh, cleanup. +diff --git a/src/core/printable.h b/src/core/printable.h +new file mode 100644 +index 0000000..8520af4 +--- /dev/null ++++ b/src/core/printable.h +@@ -0,0 +1,16 @@ ++#ifndef PRINTABLE_H ++#define PRINTABLE_H ++ ++#include <iostream> ++ ++class Printable { ++ public: ++ virtual std::string to_string() const = 0; ++}; ++ ++template<typename _CharT,class _Traits> inline std::basic_ostream<_CharT,_Traits>& ++ operator<<( std::basic_ostream<_CharT,_Traits>& out, const Printable& val) { ++ return out << val.to_string(); ++} ++ ++#endif +diff --git a/src/core/regex_namespace.h b/src/core/regex_namespace.h +new file mode 100644 +index 0000000..6e10b3c +--- /dev/null ++++ b/src/core/regex_namespace.h +@@ -0,0 +1,6 @@ ++#ifndef REGEXNAMESPACE_H ++#define REGEXNAMESPACE_H ++ ++namespace regex = utils; ++ ++#endif +diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am +index 55ea9ff..cdad48a 100644 +--- a/src/utils/Makefile.am ++++ b/src/utils/Makefile.am +@@ -9,6 +9,8 @@ libsub_utils_a_SOURCES = \ + lockfile.cc \ + lockfile.h \ + socket_fd.cc \ +- socket_fd.h ++ socket_fd.h \ ++ pattern.cc \ ++ pattern.h + + INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir) +diff --git a/src/utils/Makefile.in b/src/utils/Makefile.in +index a684a9c..5424965 100644 +--- a/src/utils/Makefile.in ++++ b/src/utils/Makefile.in +@@ -58,7 +58,7 @@ libsub_utils_a_AR = $(AR) $(ARFLAGS) + libsub_utils_a_LIBADD = + am_libsub_utils_a_OBJECTS = directory.$(OBJEXT) \ + file_status_cache.$(OBJEXT) lockfile.$(OBJEXT) \ +- socket_fd.$(OBJEXT) ++ socket_fd.$(OBJEXT) pattern.$(OBJEXT) + libsub_utils_a_OBJECTS = $(am_libsub_utils_a_OBJECTS) + DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) + depcomp = $(SHELL) $(top_srcdir)/depcomp +@@ -220,7 +220,9 @@ libsub_utils_a_SOURCES = \ + lockfile.cc \ + lockfile.h \ + socket_fd.cc \ +- socket_fd.h ++ socket_fd.h \ ++ pattern.cc \ ++ pattern.h + + INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir) + all: all-am +@@ -275,6 +277,7 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_status_cache.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lockfile.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_fd.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pattern.@am__quote@ + + .cc.o: + @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +diff --git a/src/utils/pattern.cc b/src/utils/pattern.cc +new file mode 100644 +index 0000000..c44bb38 +--- /dev/null ++++ b/src/utils/pattern.cc +@@ -0,0 +1,79 @@ ++#include <string> ++#include <sys/types.h> ++#include <ctype.h> ++#include <regex.h> ++ ++#include "pattern.h" ++ ++namespace utils { ++ ++int Pattern::countGroups( const std::string& str ) { ++ int count1 = 0; ++ int count2 = 0; ++ ++ for( size_t index = -1; (index = str.find( '(', index+1 )) != std::string::npos; ) ++ count1++; ++ for( size_t index = -1; (index = str.find( ')', index+1 )) != std::string::npos; ) ++ count2++; ++ ++ return (count1 < count2) ? count1 : count2; ++} ++ ++Pattern::Pattern( const std::string& pattern, Flags flags ) : lastResult(-1), ++ preg(NULL) { ++ int regFlags = REG_EXTENDED | REG_ICASE | REG_NEWLINE; ++ if( !(flags & CASE_SENSITIVE) ) ++ regFlags ^= REG_ICASE; ++ if( (flags & DOT_MATCH_NEWLINE) ) ++ regFlags ^= REG_NEWLINE; ++ ++ preg = new regex_t; ++ numGroups = countGroups( pattern ) + 1; ++ ++ lastResult = regcomp( preg, pattern.c_str(), regFlags ); ++} ++ ++Pattern::~Pattern() { ++ regfree( preg ); ++ delete( preg ); ++} ++ ++std::string Pattern::getLastError() const { ++ char errBuf[1024]; ++ regerror( lastResult, preg, errBuf, sizeof(errBuf) ); ++ return std::string(errBuf); ++} ++ ++Match Pattern::match( const std::string& expression ) const { ++ ++ regmatch_t* pmatch = new regmatch_t[numGroups]; ++ int res = regexec( preg, expression.c_str(), numGroups, pmatch, 0 ); ++ return Match( expression, numGroups, pmatch, res, getLastError() ); ++} ++ ++Match::Match( const std::string& expr, int ngroups, regmatch_t* groups, int result, const std::string& message ) : ++ expression( expr ), ++ nmatch( ngroups ), ++ pmatch( groups ), ++ matchResult( result ), ++ matchMessage( message ) { ++} ++ ++std::string Match::group( int i ) { ++ if( (i >= nmatch) || (pmatch[i].rm_so < 0) ) ++ return ""; ++ ++ return expression.substr( pmatch[i].rm_so, pmatch[i].rm_eo - pmatch[i].rm_so ); ++} ++ ++std::string& trim( std::string& str ) { ++ std::string::iterator it; ++ for( it = str.begin(); (it < str.end()) && ( isspace(*it) || (*it == 0) ) ; it++ ); ++ str.erase( str.begin(), it ); ++ for( it = str.end()-1; (it >= str.begin()) && ( isspace(*it) || (*it == 0) ) ; it-- ); ++ str.erase( ++it, str.end() ); ++ return str; ++} ++ ++} ++ +diff --git a/src/utils/pattern.h b/src/utils/pattern.h +new file mode 100644 +index 0000000..99e95a4 +--- /dev/null ++++ b/src/utils/pattern.h +@@ -0,0 +1,59 @@ ++#ifndef PATTERN_H ++#define PATTERN_H ++ ++#include <string> ++#include <sys/types.h> ++#include <ctype.h> ++#include <regex.h> ++ ++namespace utils { ++ ++class Match { ++ public: ++ Match( const std::string& expr, int ngroups, regmatch_t* pmatch, int matchResult, const std::string& matchMessage ); ++ ~Match() { delete[] pmatch; } ++ std::string group( int i ); ++ bool found() { return (matchResult == 0); } ++ bool matches() { return found(); } ++ std::string& getMatchMessage() { return matchMessage; } ++ ++ private: ++ std::string expression; ++ int nmatch; ++ regmatch_t* pmatch; ++ int matchResult; ++ std::string matchMessage; ++}; ++ ++class Pattern { ++ public: ++ enum Flags { ++ DEFAULT = 0, // REG_EXTENDED | REG_ICASE | REG_NEWLINE ++ CASE_SENSITIVE, ++ DOT_MATCH_NEWLINE ++ }; ++ ++ public: ++ Pattern( const std::string& pattern, Flags f = Pattern::DEFAULT ); ++ ~Pattern(); ++ bool isSuccess() { return (lastResult == 0); } ++ std::string getLastError() const; ++ Match match( const std::string& expression ) const; ++ ++ private: ++ int countGroups( const std::string& str ); ++ ++ private: ++ regex_t* preg; ++ int lastResult; ++ int numGroups; ++}; ++ ++ ++std::string& trim( std::string& str ); ++ ++} ++ ++// end of ifdef PATTERN_H ++#endif ++ |