more robust mechanism to determine external IP
This commit is contained in:
parent
8cec51fc47
commit
451c583023
|
@ -9,6 +9,7 @@ set(sources
|
||||||
bandwidth_limit
|
bandwidth_limit
|
||||||
bandwidth_manager
|
bandwidth_manager
|
||||||
bandwidth_queue_entry
|
bandwidth_queue_entry
|
||||||
|
bloom_filter
|
||||||
connection_queue
|
connection_queue
|
||||||
create_torrent
|
create_torrent
|
||||||
disk_buffer_holder
|
disk_buffer_holder
|
||||||
|
|
1
Jamfile
1
Jamfile
|
@ -368,6 +368,7 @@ SOURCES =
|
||||||
bandwidth_limit
|
bandwidth_limit
|
||||||
bandwidth_manager
|
bandwidth_manager
|
||||||
bandwidth_queue_entry
|
bandwidth_queue_entry
|
||||||
|
bloom_filter
|
||||||
connection_queue
|
connection_queue
|
||||||
create_torrent
|
create_torrent
|
||||||
disk_buffer_holder
|
disk_buffer_holder
|
||||||
|
|
|
@ -18,6 +18,7 @@ nobase_include_HEADERS = \
|
||||||
bandwidth_queue_entry.hpp \
|
bandwidth_queue_entry.hpp \
|
||||||
bencode.hpp \
|
bencode.hpp \
|
||||||
bitfield.hpp \
|
bitfield.hpp \
|
||||||
|
bloom_filter.hpp \
|
||||||
broadcast_socket.hpp \
|
broadcast_socket.hpp \
|
||||||
bt_peer_connection.hpp \
|
bt_peer_connection.hpp \
|
||||||
buffer.hpp \
|
buffer.hpp \
|
||||||
|
|
|
@ -83,6 +83,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/socket_io.hpp" // for print_address
|
#include "libtorrent/socket_io.hpp" // for print_address
|
||||||
#include "libtorrent/address.hpp"
|
#include "libtorrent/address.hpp"
|
||||||
#include "libtorrent/utp_socket_manager.hpp"
|
#include "libtorrent/utp_socket_manager.hpp"
|
||||||
|
#include "libtorrent/bloom_filter.hpp"
|
||||||
|
|
||||||
#ifdef TORRENT_STATS
|
#ifdef TORRENT_STATS
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
@ -393,7 +394,16 @@ namespace libtorrent
|
||||||
char* allocate_disk_buffer(char const* category);
|
char* allocate_disk_buffer(char const* category);
|
||||||
void free_disk_buffer(char* buf);
|
void free_disk_buffer(char* buf);
|
||||||
|
|
||||||
void set_external_address(address const& ip);
|
enum
|
||||||
|
{
|
||||||
|
source_dht = 1,
|
||||||
|
source_peer = 2,
|
||||||
|
source_tracker = 4,
|
||||||
|
source_router = 8
|
||||||
|
};
|
||||||
|
|
||||||
|
void set_external_address(address const& ip
|
||||||
|
, int source_type, address const& source);
|
||||||
address const& external_address() const { return m_external_address; }
|
address const& external_address() const { return m_external_address; }
|
||||||
|
|
||||||
// used when posting synchronous function
|
// used when posting synchronous function
|
||||||
|
@ -834,6 +844,34 @@ namespace libtorrent
|
||||||
#ifdef TORRENT_UPNP_LOGGING
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
std::ofstream m_upnp_log;
|
std::ofstream m_upnp_log;
|
||||||
#endif
|
#endif
|
||||||
|
struct external_ip_t
|
||||||
|
{
|
||||||
|
external_ip_t(): sources(0), num_votes(0) {}
|
||||||
|
|
||||||
|
bool add_vote(sha1_hash const& k, int type);
|
||||||
|
bool operator<(external_ip_t const& rhs) const
|
||||||
|
{
|
||||||
|
if (num_votes < rhs.num_votes) return true;
|
||||||
|
if (rhs.num_votes > num_votes) return false;
|
||||||
|
return sources < rhs.sources;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is a bloom filter of the IPs that have
|
||||||
|
// reported this address
|
||||||
|
bloom_filter<16> voters;
|
||||||
|
// this is the actual external address
|
||||||
|
address addr;
|
||||||
|
// a bitmask of sources the reporters have come from
|
||||||
|
boost::uint16_t sources;
|
||||||
|
// the total number of votes for this IP
|
||||||
|
boost::uint16_t num_votes;
|
||||||
|
};
|
||||||
|
|
||||||
|
// this is a bloom filter of all the IPs that have
|
||||||
|
// been the first to report an external address. Each
|
||||||
|
// IP only gets to add a new item once.
|
||||||
|
bloom_filter<32> m_external_address_voters;
|
||||||
|
std::vector<external_ip_t> m_external_addresses;
|
||||||
address m_external_address;
|
address m_external_address;
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2010, Arvid Norberg
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* 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.
|
||||||
|
* Neither the name of the author nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
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 OWNER 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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TORRENT_BLOOM_FILTER_HPP_INCLUDED
|
||||||
|
#define TORRENT_BLOOM_FILTER_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <boost/cstdint.hpp>
|
||||||
|
#include "libtorrent/peer_id.hpp" // for sha1_hash
|
||||||
|
|
||||||
|
namespace libtorrent
|
||||||
|
{
|
||||||
|
void set_bit(boost::uint32_t b, boost::uint8_t* bits, int len);
|
||||||
|
bool has_bit(boost::uint32_t b, boost::uint8_t const* bits, int len);
|
||||||
|
|
||||||
|
template <int N>
|
||||||
|
struct bloom_filter
|
||||||
|
{
|
||||||
|
bool find(sha1_hash const& k) const
|
||||||
|
{
|
||||||
|
return has_bit(k[0], bits, N)
|
||||||
|
&& has_bit(k[1], bits, N)
|
||||||
|
&& has_bit(k[2], bits, N);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(sha1_hash const& k)
|
||||||
|
{
|
||||||
|
set_bit(k[0], bits, N);
|
||||||
|
set_bit(k[1], bits, N);
|
||||||
|
set_bit(k[2], bits, N);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() { memset(bits, 0, N); }
|
||||||
|
|
||||||
|
bloom_filter() { clear(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
boost::uint8_t bits[N];
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -124,6 +124,12 @@ namespace libtorrent
|
||||||
static mutex file_mutex;
|
static mutex file_mutex;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
~logger()
|
||||||
|
{
|
||||||
|
mutex::scoped_lock l(file_mutex);
|
||||||
|
log_file.close();
|
||||||
|
}
|
||||||
|
|
||||||
logger(std::string const& logpath, std::string const& filename
|
logger(std::string const& logpath, std::string const& filename
|
||||||
, int instance, bool append)
|
, int instance, bool append)
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/io.hpp"
|
#include "libtorrent/io.hpp"
|
||||||
#include "libtorrent/error_code.hpp"
|
#include "libtorrent/error_code.hpp"
|
||||||
#include "libtorrent/lazy_entry.hpp"
|
#include "libtorrent/lazy_entry.hpp"
|
||||||
|
#include "libtorrent/peer_id.hpp" // for sha1_hash
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
|
@ -46,6 +47,7 @@ namespace libtorrent
|
||||||
TORRENT_EXPORT std::string print_endpoint(tcp::endpoint const& ep);
|
TORRENT_EXPORT std::string print_endpoint(tcp::endpoint const& ep);
|
||||||
TORRENT_EXPORT std::string print_endpoint(udp::endpoint const& ep);
|
TORRENT_EXPORT std::string print_endpoint(udp::endpoint const& ep);
|
||||||
TORRENT_EXPORT std::string address_to_bytes(address const& a);
|
TORRENT_EXPORT std::string address_to_bytes(address const& a);
|
||||||
|
TORRENT_EXPORT void hash_address(address const& ip, sha1_hash& h);
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,6 +24,7 @@ libtorrent_rasterbar_la_SOURCES = \
|
||||||
bandwidth_limit.cpp \
|
bandwidth_limit.cpp \
|
||||||
bandwidth_manager.cpp \
|
bandwidth_manager.cpp \
|
||||||
bandwidth_queue_entry.cpp \
|
bandwidth_queue_entry.cpp \
|
||||||
|
bloom_filter.cpp \
|
||||||
broadcast_socket.cpp \
|
broadcast_socket.cpp \
|
||||||
bt_peer_connection.cpp \
|
bt_peer_connection.cpp \
|
||||||
connection_queue.cpp \
|
connection_queue.cpp \
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2010, Arvid Norberg
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* 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.
|
||||||
|
* Neither the name of the author nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
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 OWNER 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 "libtorrent/bloom_filter.hpp"
|
||||||
|
|
||||||
|
namespace libtorrent
|
||||||
|
{
|
||||||
|
bool has_bit(boost::uint32_t b, boost::uint8_t const* bits, int len)
|
||||||
|
{ b %= len * 8; return bits[b/8] & (1 << (b & 7)); }
|
||||||
|
|
||||||
|
void set_bit(boost::uint32_t b, boost::uint8_t* bits, int len)
|
||||||
|
{ b %= len * 8; bits[b/8] |= (1 << (b & 7)); }
|
||||||
|
}
|
||||||
|
|
|
@ -1788,7 +1788,8 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
address_v4::bytes_type bytes;
|
address_v4::bytes_type bytes;
|
||||||
std::copy(myip.begin(), myip.end(), bytes.begin());
|
std::copy(myip.begin(), myip.end(), bytes.begin());
|
||||||
m_ses.set_external_address(address_v4(bytes));
|
m_ses.set_external_address(address_v4(bytes)
|
||||||
|
, aux::session_impl::source_peer, remote().address());
|
||||||
}
|
}
|
||||||
#if TORRENT_USE_IPV6
|
#if TORRENT_USE_IPV6
|
||||||
else if (myip.size() == address_v6::bytes_type::static_size)
|
else if (myip.size() == address_v6::bytes_type::static_size)
|
||||||
|
@ -1797,9 +1798,11 @@ namespace libtorrent
|
||||||
std::copy(myip.begin(), myip.end(), bytes.begin());
|
std::copy(myip.begin(), myip.end(), bytes.begin());
|
||||||
address_v6 ipv6_address(bytes);
|
address_v6 ipv6_address(bytes);
|
||||||
if (ipv6_address.is_v4_mapped())
|
if (ipv6_address.is_v4_mapped())
|
||||||
m_ses.set_external_address(ipv6_address.to_v4());
|
m_ses.set_external_address(ipv6_address.to_v4()
|
||||||
|
, aux::session_impl::source_peer, remote().address());
|
||||||
else
|
else
|
||||||
m_ses.set_external_address(ipv6_address);
|
m_ses.set_external_address(ipv6_address
|
||||||
|
, aux::session_impl::source_peer, remote().address());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/hasher.hpp"
|
#include "libtorrent/hasher.hpp"
|
||||||
#include "libtorrent/assert.hpp"
|
#include "libtorrent/assert.hpp"
|
||||||
#include "libtorrent/broadcast_socket.hpp" // for is_local et.al
|
#include "libtorrent/broadcast_socket.hpp" // for is_local et.al
|
||||||
|
#include "libtorrent/socket_io.hpp" // for hash_address
|
||||||
|
|
||||||
namespace libtorrent { namespace dht
|
namespace libtorrent { namespace dht
|
||||||
{
|
{
|
||||||
|
@ -96,22 +97,6 @@ int distance_exp(node_id const& n1, node_id const& n2)
|
||||||
|
|
||||||
struct static_ { static_() { std::srand(std::time(0)); } } static__;
|
struct static_ { static_() { std::srand(std::time(0)); } } static__;
|
||||||
|
|
||||||
void hash_address(address const& ip, sha1_hash& h)
|
|
||||||
{
|
|
||||||
#if TORRENT_USE_IPV6
|
|
||||||
if (ip.is_v6())
|
|
||||||
{
|
|
||||||
address_v6::bytes_type b = ip.to_v6().to_bytes();
|
|
||||||
h = hasher((char*)&b[0], b.size()).final();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
address_v4::bytes_type b = ip.to_v4().to_bytes();
|
|
||||||
h = hasher((char*)&b[0], b.size()).final();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// verifies whether a node-id matches the IP it's used from
|
// verifies whether a node-id matches the IP it's used from
|
||||||
// returns true if the node-id is OK coming from this source
|
// returns true if the node-id is OK coming from this source
|
||||||
// and false otherwise.
|
// and false otherwise.
|
||||||
|
|
|
@ -346,7 +346,7 @@ bool rpc_manager::incoming(msg const& m, node_id* id)
|
||||||
// this node claims we use the wrong node-ID!
|
// this node claims we use the wrong node-ID!
|
||||||
address_v4::bytes_type b;
|
address_v4::bytes_type b;
|
||||||
memcpy(&b[0], ext_ip->string_ptr(), 4);
|
memcpy(&b[0], ext_ip->string_ptr(), 4);
|
||||||
m_ses.set_external_address(address_v4(b));
|
m_ses.set_external_address(address_v4(b), aux::session_impl::source_dht, m.addr.address());
|
||||||
}
|
}
|
||||||
#if TORRENT_USE_IPV6
|
#if TORRENT_USE_IPV6
|
||||||
else if (ext_ip && ext_ip->string_length() == 16)
|
else if (ext_ip && ext_ip->string_length() == 16)
|
||||||
|
@ -354,7 +354,7 @@ bool rpc_manager::incoming(msg const& m, node_id* id)
|
||||||
// this node claims we use the wrong node-ID!
|
// this node claims we use the wrong node-ID!
|
||||||
address_v6::bytes_type b;
|
address_v6::bytes_type b;
|
||||||
memcpy(&b[0], ext_ip->string_ptr(), 16);
|
memcpy(&b[0], ext_ip->string_ptr(), 16);
|
||||||
m_ses.set_external_address(address_v6(b));
|
m_ses.set_external_address(address_v6(b), aux::session_impl::source_dht, m.addr.address());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -900,11 +900,6 @@ namespace aux {
|
||||||
save_struct(e[c.name], reinterpret_cast<char const*>(this) + c.offset
|
save_struct(e[c.name], reinterpret_cast<char const*>(this) + c.offset
|
||||||
, c.map, c.num_entries, reinterpret_cast<char const*>(&def) + c.default_offset);
|
, c.map, c.num_entries, reinterpret_cast<char const*>(&def) + c.default_offset);
|
||||||
}
|
}
|
||||||
#ifndef TORRENT_DISABLE_DHT
|
|
||||||
if (flags & session::save_dht_settings)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifndef TORRENT_DISABLE_DHT
|
#ifndef TORRENT_DISABLE_DHT
|
||||||
if (m_dht && (flags & session::save_dht_state))
|
if (m_dht && (flags & session::save_dht_state))
|
||||||
{
|
{
|
||||||
|
@ -3720,7 +3715,9 @@ namespace aux {
|
||||||
|
|
||||||
if (mapping == m_tcp_mapping[map_transport] && port != 0)
|
if (mapping == m_tcp_mapping[map_transport] && port != 0)
|
||||||
{
|
{
|
||||||
if (ip != address()) set_external_address(ip);
|
// TODO: report the proper address of the router
|
||||||
|
if (ip != address()) set_external_address(ip, source_router
|
||||||
|
, address());
|
||||||
|
|
||||||
if (!m_listen_sockets.empty()) {
|
if (!m_listen_sockets.empty()) {
|
||||||
m_listen_sockets.front().external_address = ip;
|
m_listen_sockets.front().external_address = ip;
|
||||||
|
@ -3994,10 +3991,6 @@ namespace aux {
|
||||||
|
|
||||||
session_impl::~session_impl()
|
session_impl::~session_impl()
|
||||||
{
|
{
|
||||||
#if defined BOOST_HAS_PTHREADS
|
|
||||||
TORRENT_ASSERT(!is_network_thread());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
(*m_logger) << time_now_string() << "\n\n *** shutting down session *** \n\n";
|
(*m_logger) << time_now_string() << "\n\n *** shutting down session *** \n\n";
|
||||||
#endif
|
#endif
|
||||||
|
@ -4026,7 +4019,7 @@ namespace aux {
|
||||||
printf("\n==== Waiting to shut down: %d ==== \n\n", counter);
|
printf("\n==== Waiting to shut down: %d ==== \n\n", counter);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
m_thread->join();
|
if (m_thread) m_thread->join();
|
||||||
|
|
||||||
TORRENT_ASSERT(m_torrents.empty());
|
TORRENT_ASSERT(m_torrents.empty());
|
||||||
TORRENT_ASSERT(m_connections.empty());
|
TORRENT_ASSERT(m_connections.empty());
|
||||||
|
@ -4367,18 +4360,95 @@ namespace aux {
|
||||||
m_upnp = 0;
|
m_upnp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void session_impl::set_external_address(address const& ip)
|
bool session_impl::external_ip_t::add_vote(sha1_hash const& k, int type)
|
||||||
|
{
|
||||||
|
sources |= type;
|
||||||
|
if (voters.find(k)) return false;
|
||||||
|
voters.set(k);
|
||||||
|
++num_votes;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void session_impl::set_external_address(address const& ip
|
||||||
|
, int source_type, address const& source)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(ip != address());
|
TORRENT_ASSERT(ip != address());
|
||||||
|
|
||||||
if (is_local(ip)) return;
|
if (is_local(ip)) return;
|
||||||
if (is_loopback(ip)) return;
|
if (is_loopback(ip)) return;
|
||||||
if (m_external_address == ip) return;
|
|
||||||
|
|
||||||
// for now, just trust whoever tells us our external address first
|
#if defined TORRENT_VERBOSE_LOGGING
|
||||||
if (m_external_address != address()) return;
|
(*m_logger) << time_now_string() << ": set_external_address(" << print_address(ip)
|
||||||
|
<< ", " << source_type << ", " << print_address(source) << ")\n";
|
||||||
|
#endif
|
||||||
|
// this is the key to use for the bloom filters
|
||||||
|
// it represents the identity of the voter
|
||||||
|
sha1_hash k;
|
||||||
|
hash_address(source, k);
|
||||||
|
|
||||||
|
// do we already have an entry for this external IP?
|
||||||
|
std::vector<external_ip_t>::iterator i = std::find_if(m_external_addresses.begin()
|
||||||
|
, m_external_addresses.end(), boost::bind(&external_ip_t::addr, _1) == ip);
|
||||||
|
|
||||||
|
if (i == m_external_addresses.end())
|
||||||
|
{
|
||||||
|
// each IP only gets to add a new IP once
|
||||||
|
if (m_external_address_voters.find(k)) return;
|
||||||
|
|
||||||
|
if (m_external_addresses.size() > 20)
|
||||||
|
{
|
||||||
|
if (rand() < RAND_MAX / 2)
|
||||||
|
{
|
||||||
|
#if defined TORRENT_VERBOSE_LOGGING
|
||||||
|
(*m_logger) << time_now_string() << ": More than 20 slots, dopped\n";
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// use stable sort here to maintain the fifo-order
|
||||||
|
// of the entries with the same number of votes
|
||||||
|
// this will sort in ascending order, i.e. the lowest
|
||||||
|
// votes first. Also, the oldest are first, so this
|
||||||
|
// is a sort of weighted LRU.
|
||||||
|
std::stable_sort(m_external_addresses.begin(), m_external_addresses.end());
|
||||||
|
// erase the first element, since this is the
|
||||||
|
// oldest entry and the one with lowst number
|
||||||
|
// of votes. This makes sense because the oldest
|
||||||
|
// entry has had the longest time to receive more
|
||||||
|
// votes to be bumped up
|
||||||
|
#if defined TORRENT_VERBOSE_LOGGING
|
||||||
|
(*m_logger) << " More than 20 slots, dopping "
|
||||||
|
<< print_address(m_external_addresses.front().addr)
|
||||||
|
<< " (" << m_external_addresses.front().num_votes << ")\n";
|
||||||
|
#endif
|
||||||
|
m_external_addresses.erase(m_external_addresses.begin());
|
||||||
|
}
|
||||||
|
m_external_addresses.push_back(external_ip_t());
|
||||||
|
i = m_external_addresses.end() - 1;
|
||||||
|
i->addr = ip;
|
||||||
|
}
|
||||||
|
// add one more vote to this external IP
|
||||||
|
if (!i->add_vote(k, source_type)) return;
|
||||||
|
|
||||||
|
i = std::max_element(m_external_addresses.begin(), m_external_addresses.end());
|
||||||
|
TORRENT_ASSERT(i != m_external_addresses.end());
|
||||||
|
|
||||||
|
#if defined TORRENT_VERBOSE_LOGGING
|
||||||
|
for (std::vector<external_ip_t>::iterator j = m_external_addresses.begin()
|
||||||
|
, end(m_external_addresses.end()); j != end; ++j)
|
||||||
|
{
|
||||||
|
(*m_logger) << ((j == i)?"-->":" ")
|
||||||
|
<< print_address(j->addr) << " votes: "
|
||||||
|
<< j->num_votes << "\n";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (i->addr == m_external_address) return;
|
||||||
|
|
||||||
|
#if defined TORRENT_VERBOSE_LOGGING
|
||||||
|
(*m_logger) << " external IP updated\n";
|
||||||
|
#endif
|
||||||
|
m_external_address = i->addr;
|
||||||
|
m_external_address_voters.clear();
|
||||||
|
|
||||||
m_external_address = ip;
|
|
||||||
if (m_alerts.should_post<external_ip_alert>())
|
if (m_alerts.should_post<external_ip_alert>())
|
||||||
m_alerts.post_alert(external_ip_alert(ip));
|
m_alerts.post_alert(external_ip_alert(ip));
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/socket.hpp"
|
#include "libtorrent/socket.hpp"
|
||||||
#include "libtorrent/socket_io.hpp"
|
#include "libtorrent/socket_io.hpp"
|
||||||
#include "libtorrent/address.hpp"
|
#include "libtorrent/address.hpp"
|
||||||
|
#include "libtorrent/hasher.hpp" // for hasher
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
|
@ -92,5 +93,21 @@ namespace libtorrent
|
||||||
return print_endpoint(tcp::endpoint(ep.address(), ep.port()));
|
return print_endpoint(tcp::endpoint(ep.address(), ep.port()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hash_address(address const& ip, sha1_hash& h)
|
||||||
|
{
|
||||||
|
#if TORRENT_USE_IPV6
|
||||||
|
if (ip.is_v6())
|
||||||
|
{
|
||||||
|
address_v6::bytes_type b = ip.to_v6().to_bytes();
|
||||||
|
h = hasher((char*)&b[0], b.size()).final();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
address_v4::bytes_type b = ip.to_v4().to_bytes();
|
||||||
|
h = hasher((char*)&b[0], b.size()).final();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1743,8 +1743,10 @@ namespace libtorrent
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
TORRENT_ASSERT(r.kind == tracker_request::announce_request);
|
TORRENT_ASSERT(r.kind == tracker_request::announce_request);
|
||||||
|
|
||||||
|
TORRENT_ASSERT(!tracker_ips.empty());
|
||||||
if (external_ip != address())
|
if (external_ip != address())
|
||||||
m_ses.set_external_address(external_ip);
|
m_ses.set_external_address(external_ip, aux::session_impl::source_tracker
|
||||||
|
, *tracker_ips.begin());
|
||||||
|
|
||||||
ptime now = time_now();
|
ptime now = time_now();
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/bencode.hpp"
|
#include "libtorrent/bencode.hpp"
|
||||||
#include "libtorrent/timestamp_history.hpp"
|
#include "libtorrent/timestamp_history.hpp"
|
||||||
#include "libtorrent/enum_net.hpp"
|
#include "libtorrent/enum_net.hpp"
|
||||||
|
#include "libtorrent/bloom_filter.hpp"
|
||||||
|
#include "libtorrent/aux_/session_impl.hpp"
|
||||||
#ifndef TORRENT_DISABLE_DHT
|
#ifndef TORRENT_DISABLE_DHT
|
||||||
#include "libtorrent/kademlia/node_id.hpp"
|
#include "libtorrent/kademlia/node_id.hpp"
|
||||||
#include "libtorrent/kademlia/routing_table.hpp"
|
#include "libtorrent/kademlia/routing_table.hpp"
|
||||||
|
@ -379,12 +381,89 @@ namespace libtorrent
|
||||||
|
|
||||||
TORRENT_EXPORT void find_control_url(int type, char const* string, parse_state& state);
|
TORRENT_EXPORT void find_control_url(int type, char const* string, parse_state& state);
|
||||||
|
|
||||||
|
address rand_v4()
|
||||||
|
{
|
||||||
|
return address_v4(rand() << 16 | rand());
|
||||||
|
}
|
||||||
|
|
||||||
int test_main()
|
int test_main()
|
||||||
{
|
{
|
||||||
using namespace libtorrent;
|
using namespace libtorrent;
|
||||||
error_code ec;
|
error_code ec;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
// test external ip voting
|
||||||
|
aux::session_impl* ses = new aux::session_impl(std::pair<int, int>(0,0)
|
||||||
|
, fingerprint("LT", 0, 0, 0, 0), "0.0.0.0"
|
||||||
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||||
|
, ""
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
|
// test a single malicious node
|
||||||
|
// adds 50 legitimate responses from different peers
|
||||||
|
// and 50 malicious responses from the same peer
|
||||||
|
address real_external = address_v4::from_string("5.5.5.5");
|
||||||
|
address malicious = address_v4::from_string("4.4.4.4");
|
||||||
|
for (int i = 0; i < 50; ++i)
|
||||||
|
{
|
||||||
|
ses->set_external_address(real_external, aux::session_impl::source_dht, rand_v4());
|
||||||
|
ses->set_external_address(rand_v4(), aux::session_impl::source_dht, malicious);
|
||||||
|
}
|
||||||
|
TEST_CHECK(ses->external_address() == real_external);
|
||||||
|
ses->abort();
|
||||||
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||||
|
ses->m_logger.reset();
|
||||||
|
#endif
|
||||||
|
delete ses;
|
||||||
|
ses = new aux::session_impl(std::pair<int, int>(0,0)
|
||||||
|
, fingerprint("LT", 0, 0, 0, 0), "0.0.0.0"
|
||||||
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||||
|
, ""
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
|
// test a single malicious node
|
||||||
|
// adds 50 legitimate responses from different peers
|
||||||
|
// and 50 consistent malicious responses from the same peer
|
||||||
|
real_external = address_v4::from_string("5.5.5.5");
|
||||||
|
malicious = address_v4::from_string("4.4.4.4");
|
||||||
|
address malicious_external = address_v4::from_string("3.3.3.3");
|
||||||
|
for (int i = 0; i < 50; ++i)
|
||||||
|
{
|
||||||
|
ses->set_external_address(real_external, aux::session_impl::source_dht, rand_v4());
|
||||||
|
ses->set_external_address(malicious_external, aux::session_impl::source_dht, malicious);
|
||||||
|
}
|
||||||
|
TEST_CHECK(ses->external_address() == real_external);
|
||||||
|
ses->abort();
|
||||||
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||||
|
ses->m_logger.reset();
|
||||||
|
#endif
|
||||||
|
delete ses;
|
||||||
|
|
||||||
|
// test bloom_filter
|
||||||
|
bloom_filter<32> filter;
|
||||||
|
sha1_hash k1 = hasher("test1", 5).final();
|
||||||
|
sha1_hash k2 = hasher("test2", 5).final();
|
||||||
|
sha1_hash k3 = hasher("test3", 5).final();
|
||||||
|
sha1_hash k4 = hasher("test4", 5).final();
|
||||||
|
TEST_CHECK(!filter.find(k1));
|
||||||
|
TEST_CHECK(!filter.find(k2));
|
||||||
|
TEST_CHECK(!filter.find(k3));
|
||||||
|
TEST_CHECK(!filter.find(k4));
|
||||||
|
|
||||||
|
filter.set(k1);
|
||||||
|
TEST_CHECK(filter.find(k1));
|
||||||
|
TEST_CHECK(!filter.find(k2));
|
||||||
|
TEST_CHECK(!filter.find(k3));
|
||||||
|
TEST_CHECK(!filter.find(k4));
|
||||||
|
|
||||||
|
filter.set(k4);
|
||||||
|
TEST_CHECK(filter.find(k1));
|
||||||
|
TEST_CHECK(!filter.find(k2));
|
||||||
|
TEST_CHECK(!filter.find(k3));
|
||||||
|
TEST_CHECK(filter.find(k4));
|
||||||
|
|
||||||
// test timestamp_history
|
// test timestamp_history
|
||||||
{
|
{
|
||||||
timestamp_history h;
|
timestamp_history h;
|
||||||
|
|
Loading…
Reference in New Issue