forked from premiere/premiere-libtorrent
added port filter for outgoing connections
This commit is contained in:
parent
aea4e503c5
commit
d0412a2244
|
@ -224,6 +224,7 @@ namespace libtorrent
|
|||
bool is_aborted() const { return m_abort; }
|
||||
|
||||
void set_ip_filter(ip_filter const& f);
|
||||
void set_port_filter(port_filter const& f);
|
||||
|
||||
bool listen_on(
|
||||
std::pair<int, int> const& port_range
|
||||
|
@ -351,6 +352,9 @@ namespace libtorrent
|
|||
|
||||
// filters incoming connections
|
||||
ip_filter m_ip_filter;
|
||||
|
||||
// filters outgoing connections
|
||||
port_filter m_port_filter;
|
||||
|
||||
// the peer id that is generated at the start of the session
|
||||
peer_id m_peer_id;
|
||||
|
|
|
@ -71,20 +71,82 @@ struct ip_range
|
|||
namespace detail
|
||||
{
|
||||
|
||||
template<class Addr>
|
||||
Addr zero()
|
||||
{
|
||||
typename Addr::bytes_type zero;
|
||||
std::fill(zero.begin(), zero.end(), 0);
|
||||
return Addr(zero);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline boost::uint16_t zero<boost::uint16_t>() { return 0; }
|
||||
|
||||
template<class Addr>
|
||||
Addr plus_one(Addr const& a)
|
||||
{
|
||||
typename Addr::bytes_type tmp(a.to_bytes());
|
||||
typedef typename Addr::bytes_type::reverse_iterator iter;
|
||||
for (iter i = tmp.rbegin()
|
||||
, end(tmp.rend()); i != end; ++i)
|
||||
{
|
||||
if (*i < (std::numeric_limits<typename iter::value_type>::max)())
|
||||
{
|
||||
*i += 1;
|
||||
break;
|
||||
}
|
||||
*i = 0;
|
||||
}
|
||||
return Addr(tmp);
|
||||
}
|
||||
|
||||
inline boost::uint16_t plus_one(boost::uint16_t val) { return val + 1; }
|
||||
|
||||
template<class Addr>
|
||||
Addr minus_one(Addr const& a)
|
||||
{
|
||||
typename Addr::bytes_type tmp(a.to_bytes());
|
||||
typedef typename Addr::bytes_type::reverse_iterator iter;
|
||||
for (iter i = tmp.rbegin()
|
||||
, end(tmp.rend()); i != end; ++i)
|
||||
{
|
||||
if (*i > 0)
|
||||
{
|
||||
*i -= 1;
|
||||
break;
|
||||
}
|
||||
*i = (std::numeric_limits<typename iter::value_type>::max)();
|
||||
}
|
||||
return Addr(tmp);
|
||||
}
|
||||
|
||||
inline boost::uint16_t minus_one(boost::uint16_t val) { return val - 1; }
|
||||
|
||||
template<class Addr>
|
||||
Addr max_addr()
|
||||
{
|
||||
typename Addr::bytes_type tmp;
|
||||
std::fill(tmp.begin(), tmp.end()
|
||||
, (std::numeric_limits<typename Addr::bytes_type::value_type>::max)());
|
||||
return Addr(tmp);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline boost::uint16_t max_addr<boost::uint16_t>()
|
||||
{ return std::numeric_limits<boost::uint16_t>::max(); }
|
||||
|
||||
// this is the generic implementation of
|
||||
// a filter for a specific address type.
|
||||
// it works with IPv4 and IPv6
|
||||
template<class Addr>
|
||||
class TORRENT_EXPORT filter_impl
|
||||
class filter_impl
|
||||
{
|
||||
public:
|
||||
|
||||
filter_impl()
|
||||
{
|
||||
typename Addr::bytes_type zero;
|
||||
std::fill(zero.begin(), zero.end(), 0);
|
||||
// make the entire ip-range non-blocked
|
||||
m_access_list.insert(range(Addr(zero), 0));
|
||||
m_access_list.insert(range(zero<Addr>(), 0));
|
||||
}
|
||||
|
||||
void add_rule(Addr first, Addr last, int flags)
|
||||
|
@ -134,7 +196,7 @@ namespace detail
|
|||
if ((j != m_access_list.end()
|
||||
&& minus_one(j->start) != last)
|
||||
|| (j == m_access_list.end()
|
||||
&& last != max_addr()))
|
||||
&& last != max_addr<Addr>()))
|
||||
{
|
||||
assert(j == m_access_list.end() || last < minus_one(j->start));
|
||||
if (last_access != flags)
|
||||
|
@ -170,7 +232,7 @@ namespace detail
|
|||
|
||||
++i;
|
||||
if (i == end)
|
||||
r.last = max_addr();
|
||||
r.last = max_addr<Addr>();
|
||||
else
|
||||
r.last = minus_one(i->start);
|
||||
|
||||
|
@ -181,48 +243,6 @@ namespace detail
|
|||
|
||||
private:
|
||||
|
||||
Addr plus_one(Addr const& a) const
|
||||
{
|
||||
typename Addr::bytes_type tmp(a.to_bytes());
|
||||
typedef typename Addr::bytes_type::reverse_iterator iter;
|
||||
for (iter i = tmp.rbegin()
|
||||
, end(tmp.rend()); i != end; ++i)
|
||||
{
|
||||
if (*i < (std::numeric_limits<typename iter::value_type>::max)())
|
||||
{
|
||||
*i += 1;
|
||||
break;
|
||||
}
|
||||
*i = 0;
|
||||
}
|
||||
return Addr(tmp);
|
||||
}
|
||||
|
||||
Addr minus_one(Addr const& a) const
|
||||
{
|
||||
typename Addr::bytes_type tmp(a.to_bytes());
|
||||
typedef typename Addr::bytes_type::reverse_iterator iter;
|
||||
for (iter i = tmp.rbegin()
|
||||
, end(tmp.rend()); i != end; ++i)
|
||||
{
|
||||
if (*i > 0)
|
||||
{
|
||||
*i -= 1;
|
||||
break;
|
||||
}
|
||||
*i = (std::numeric_limits<typename iter::value_type>::max)();
|
||||
}
|
||||
return Addr(tmp);
|
||||
}
|
||||
|
||||
Addr max_addr() const
|
||||
{
|
||||
typename Addr::bytes_type tmp;
|
||||
std::fill(tmp.begin(), tmp.end()
|
||||
, (std::numeric_limits<typename Addr::bytes_type::value_type>::max)());
|
||||
return Addr(tmp);
|
||||
}
|
||||
|
||||
struct range
|
||||
{
|
||||
range(Addr addr, int access = 0): start(addr), access(access) {}
|
||||
|
@ -270,6 +290,24 @@ private:
|
|||
detail::filter_impl<address_v6> m_filter6;
|
||||
};
|
||||
|
||||
class TORRENT_EXPORT port_filter
|
||||
{
|
||||
public:
|
||||
|
||||
enum access_flags
|
||||
{
|
||||
blocked = 1
|
||||
};
|
||||
|
||||
void add_rule(boost::uint16_t first, boost::uint16_t last, int flags);
|
||||
int access(boost::uint16_t port) const;
|
||||
|
||||
private:
|
||||
|
||||
detail::filter_impl<boost::uint16_t> m_filter;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -72,6 +72,7 @@ namespace libtorrent
|
|||
struct torrent_plugin;
|
||||
class torrent;
|
||||
class ip_filter;
|
||||
class port_filter;
|
||||
class connection_queue;
|
||||
|
||||
namespace aux
|
||||
|
@ -182,6 +183,7 @@ namespace libtorrent
|
|||
#endif
|
||||
|
||||
void set_ip_filter(ip_filter const& f);
|
||||
void set_port_filter(port_filter const& f);
|
||||
void set_peer_id(peer_id const& pid);
|
||||
void set_key(int key);
|
||||
|
||||
|
|
|
@ -69,6 +69,15 @@ namespace libtorrent
|
|||
, m_filter6.export_filter());
|
||||
}
|
||||
|
||||
void port_filter::add_rule(boost::uint16_t first, boost::uint16_t last, int flags)
|
||||
{
|
||||
m_filter.add_rule(first, last, flags);
|
||||
}
|
||||
|
||||
int port_filter::access(boost::uint16_t port) const
|
||||
{
|
||||
return m_filter.access(port);
|
||||
}
|
||||
/*
|
||||
void ip_filter::print() const
|
||||
{
|
||||
|
|
|
@ -524,6 +524,8 @@ namespace libtorrent
|
|||
int max_failcount = m_torrent->settings().max_failcount;
|
||||
int min_reconnect_time = m_torrent->settings().min_reconnect_time;
|
||||
|
||||
aux::session_impl& ses = m_torrent->session();
|
||||
|
||||
for (iterator i = m_peers.begin(); i != m_peers.end(); ++i)
|
||||
{
|
||||
if (i->connection) continue;
|
||||
|
@ -533,6 +535,8 @@ namespace libtorrent
|
|||
if (i->failcount >= max_failcount) continue;
|
||||
if (now - i->connected < seconds(i->failcount * min_reconnect_time))
|
||||
continue;
|
||||
if (ses.m_port_filter.access(i->ip.port()) & port_filter::blocked)
|
||||
continue;
|
||||
|
||||
assert(i->connected <= now);
|
||||
|
||||
|
@ -968,6 +972,19 @@ namespace libtorrent
|
|||
if(remote.address() == address() || remote.port() == 0)
|
||||
return;
|
||||
|
||||
aux::session_impl& ses = m_torrent->session();
|
||||
|
||||
port_filter const& pf = ses.m_port_filter;
|
||||
if (pf.access(remote.port()) & port_filter::blocked)
|
||||
{
|
||||
if (ses.m_alerts.should_post(alert::info))
|
||||
{
|
||||
ses.m_alerts.post_alert(peer_blocked_alert(remote.address()
|
||||
, "outgoing port blocked, peer not added to peer list"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
iterator i;
|
||||
|
@ -986,8 +1003,6 @@ namespace libtorrent
|
|||
|
||||
if (i == m_peers.end())
|
||||
{
|
||||
aux::session_impl& ses = m_torrent->session();
|
||||
|
||||
// if the IP is blocked, don't add it
|
||||
if (ses.m_ip_filter.access(remote.address()) & ip_filter::blocked)
|
||||
{
|
||||
|
|
|
@ -143,6 +143,11 @@ namespace libtorrent
|
|||
m_impl->set_ip_filter(f);
|
||||
}
|
||||
|
||||
void session::set_port_filter(port_filter const& f)
|
||||
{
|
||||
m_impl->set_port_filter(f);
|
||||
}
|
||||
|
||||
void session::set_peer_id(peer_id const& id)
|
||||
{
|
||||
m_impl->set_peer_id(id);
|
||||
|
|
|
@ -582,6 +582,12 @@ namespace libtorrent { namespace detail
|
|||
m_checker_impl.m_abort = true;
|
||||
}
|
||||
|
||||
void session_impl::set_port_filter(port_filter const& f)
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
m_port_filter = f;
|
||||
}
|
||||
|
||||
void session_impl::set_ip_filter(ip_filter const& f)
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
|
|
|
@ -171,6 +171,25 @@ int test_main()
|
|||
|
||||
}
|
||||
|
||||
port_filter pf;
|
||||
|
||||
// default contructed port filter should allow any port
|
||||
TEST_CHECK(pf.access(0) == 0);
|
||||
TEST_CHECK(pf.access(65535) == 0);
|
||||
TEST_CHECK(pf.access(6881) == 0);
|
||||
|
||||
// block port 100 - 300
|
||||
pf.add_rule(100, 300, port_filter::blocked);
|
||||
|
||||
TEST_CHECK(pf.access(0) == 0);
|
||||
TEST_CHECK(pf.access(99) == 0);
|
||||
TEST_CHECK(pf.access(100) == port_filter::blocked);
|
||||
TEST_CHECK(pf.access(150) == port_filter::blocked);
|
||||
TEST_CHECK(pf.access(300) == port_filter::blocked);
|
||||
TEST_CHECK(pf.access(301) == 0);
|
||||
TEST_CHECK(pf.access(6881) == 0);
|
||||
TEST_CHECK(pf.access(65535) == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue