made peer connection order depend on ones external IP or be random (if we don't know our external IP). Should fix #281
This commit is contained in:
parent
60add53428
commit
cf5c9344ab
|
@ -382,6 +382,8 @@ namespace libtorrent
|
||||||
void free_buffer(char* buf, int size);
|
void free_buffer(char* buf, int size);
|
||||||
void free_disk_buffer(char* buf);
|
void free_disk_buffer(char* buf);
|
||||||
|
|
||||||
|
address m_external_address;
|
||||||
|
|
||||||
// private:
|
// private:
|
||||||
|
|
||||||
void on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih);
|
void on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih);
|
||||||
|
|
|
@ -45,6 +45,10 @@ namespace libtorrent
|
||||||
bool is_loopback(address const& addr);
|
bool is_loopback(address const& addr);
|
||||||
bool is_multicast(address const& addr);
|
bool is_multicast(address const& addr);
|
||||||
bool is_any(address const& addr);
|
bool is_any(address const& addr);
|
||||||
|
int cidr_distance(address const& a1, address const& a2);
|
||||||
|
|
||||||
|
int common_bits(unsigned char const* b1
|
||||||
|
, unsigned char const* b2, int n);
|
||||||
|
|
||||||
address guess_local_address(asio::io_service&);
|
address guess_local_address(asio::io_service&);
|
||||||
|
|
||||||
|
|
|
@ -99,6 +99,44 @@ namespace libtorrent
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// count the length of the common bit prefix
|
||||||
|
int common_bits(unsigned char const* b1
|
||||||
|
, unsigned char const* b2, int n)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < n; ++i, ++b1, ++b2)
|
||||||
|
{
|
||||||
|
unsigned char a = *b1 ^ *b2;
|
||||||
|
if (a == 0) continue;
|
||||||
|
int ret = i * 8 + 8;
|
||||||
|
for (; a > 0; a >>= 1) --ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return n * 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the number of bits in that differ from the right
|
||||||
|
// between the addresses.
|
||||||
|
int cidr_distance(address const& a1, address const& a2)
|
||||||
|
{
|
||||||
|
if (a1.is_v4() == a2.is_v4())
|
||||||
|
{
|
||||||
|
// both are v4
|
||||||
|
address_v4::bytes_type b1 = a1.to_v4().to_bytes();
|
||||||
|
address_v4::bytes_type b2 = a2.to_v4().to_bytes();
|
||||||
|
return address_v4::bytes_type::static_size * 8
|
||||||
|
- common_bits(b1.c_array(), b2.c_array(), b1.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
address_v6::bytes_type b1;
|
||||||
|
address_v6::bytes_type b2;
|
||||||
|
if (a1.is_v4()) b1 = address_v6::v4_mapped(a1.to_v4()).to_bytes();
|
||||||
|
else b1 = a1.to_v6().to_bytes();
|
||||||
|
if (a2.is_v4()) b2 = address_v6::v4_mapped(a2.to_v4()).to_bytes();
|
||||||
|
else b2 = a2.to_v6().to_bytes();
|
||||||
|
return address_v6::bytes_type::static_size * 8
|
||||||
|
- common_bits(b1.c_array(), b2.c_array(), b1.size());
|
||||||
|
}
|
||||||
|
|
||||||
broadcast_socket::broadcast_socket(asio::io_service& ios
|
broadcast_socket::broadcast_socket(asio::io_service& ios
|
||||||
, udp::endpoint const& multicast_endpoint
|
, udp::endpoint const& multicast_endpoint
|
||||||
, receive_handler_t const& handler
|
, receive_handler_t const& handler
|
||||||
|
|
|
@ -1285,6 +1285,27 @@ namespace libtorrent
|
||||||
if (m_max_out_request_queue < 1)
|
if (m_max_out_request_queue < 1)
|
||||||
m_max_out_request_queue = 1;
|
m_max_out_request_queue = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (entry* myip = root.find_key("yourip"))
|
||||||
|
{
|
||||||
|
// TODO: don't trust this blindly
|
||||||
|
if (myip->type() == entry::string_t)
|
||||||
|
{
|
||||||
|
std::string const& my_ip = myip->string().c_str();
|
||||||
|
if (my_ip.size() == address_v4::bytes_type::static_size)
|
||||||
|
{
|
||||||
|
address_v4::bytes_type bytes;
|
||||||
|
std::copy(my_ip.begin(), my_ip.end(), bytes.begin());
|
||||||
|
m_ses.m_external_address = address_v4(bytes);
|
||||||
|
}
|
||||||
|
else if (my_ip.size() == address_v6::bytes_type::static_size)
|
||||||
|
{
|
||||||
|
address_v6::bytes_type bytes;
|
||||||
|
std::copy(my_ip.begin(), my_ip.end(), bytes.begin());
|
||||||
|
m_ses.m_external_address = address_v6(bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bt_peer_connection::dispatch_message(int received)
|
bool bt_peer_connection::dispatch_message(int received)
|
||||||
|
|
|
@ -528,7 +528,18 @@ namespace libtorrent
|
||||||
|
|
||||||
int max_failcount = m_torrent->settings().max_failcount;
|
int max_failcount = m_torrent->settings().max_failcount;
|
||||||
int min_reconnect_time = m_torrent->settings().min_reconnect_time;
|
int min_reconnect_time = m_torrent->settings().min_reconnect_time;
|
||||||
|
int min_cidr_distance = (std::numeric_limits<int>::max)();
|
||||||
bool finished = m_torrent->is_finished();
|
bool finished = m_torrent->is_finished();
|
||||||
|
address external_ip = m_torrent->session().m_external_address;
|
||||||
|
|
||||||
|
if (external_ip == address())
|
||||||
|
{
|
||||||
|
// set external_ip to a random value, to
|
||||||
|
// radomize which peers we prefer
|
||||||
|
address_v4::bytes_type bytes;
|
||||||
|
std::generate(bytes.begin(), bytes.end(), &std::rand);
|
||||||
|
external_ip = address_v4(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
aux::session_impl& ses = m_torrent->session();
|
aux::session_impl& ses = m_torrent->session();
|
||||||
|
|
||||||
|
@ -560,15 +571,29 @@ namespace libtorrent
|
||||||
&& !is_local(i->second.ip.address()))
|
&& !is_local(i->second.ip.address()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (i->second.connected <= min_connect_time)
|
if (i->second.connected > min_connect_time) continue;
|
||||||
{
|
int distance = cidr_distance(external_ip, i->second.ip.address());
|
||||||
min_connect_time = i->second.connected;
|
if (distance > min_cidr_distance) continue;
|
||||||
candidate = i;
|
|
||||||
}
|
min_cidr_distance = distance;
|
||||||
|
min_connect_time = i->second.connected;
|
||||||
|
candidate = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_ASSERT(min_connect_time <= now);
|
TORRENT_ASSERT(min_connect_time <= now);
|
||||||
|
|
||||||
|
#if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING
|
||||||
|
if (candidate != m_peers.end())
|
||||||
|
{
|
||||||
|
(*m_torrent->session().m_logger) << "*** FOUND CONNECTION CANDIDATE ["
|
||||||
|
" ip: " << candidate->second.ip <<
|
||||||
|
" d: " << min_cidr_distance <<
|
||||||
|
" external: " << external_ip <<
|
||||||
|
" t: " << total_seconds(time_now() - min_connect_time) <<
|
||||||
|
" ]\n";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return candidate;
|
return candidate;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -943,7 +968,7 @@ namespace libtorrent
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
|
||||||
if (c.remote().address() == m_torrent->current_tracker().address())
|
if (c.remote().address() == m_torrent->current_tracker().address())
|
||||||
{
|
{
|
||||||
m_torrent->debug_log("overriding connection limit for tracker NAT-check");
|
m_torrent->debug_log("overriding connection limit for tracker NAT-check");
|
||||||
|
@ -985,7 +1010,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
|
||||||
m_torrent->debug_log("duplicate connection. existing connection"
|
m_torrent->debug_log("duplicate connection. existing connection"
|
||||||
" is connecting and this connection is incoming. closing existing "
|
" is connecting and this connection is incoming. closing existing "
|
||||||
"connection in favour of this one");
|
"connection in favour of this one");
|
||||||
|
@ -1153,7 +1178,7 @@ namespace libtorrent
|
||||||
// so we don't have to trust this source
|
// so we don't have to trust this source
|
||||||
if ((flags & 0x02) && !i->second.connection) i->second.seed = true;
|
if ((flags & 0x02) && !i->second.connection) i->second.seed = true;
|
||||||
|
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
|
||||||
if (i->second.connection)
|
if (i->second.connection)
|
||||||
{
|
{
|
||||||
// this means we're already connected
|
// this means we're already connected
|
||||||
|
@ -1249,7 +1274,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
m_torrent->session().unchoke_peer(c);
|
m_torrent->session().unchoke_peer(c);
|
||||||
}
|
}
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING)
|
#if defined TORRENT_VERBOSE_LOGGING
|
||||||
else if (c.is_choked())
|
else if (c.is_choked())
|
||||||
{
|
{
|
||||||
std::string reason;
|
std::string reason;
|
||||||
|
@ -1362,7 +1387,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING)
|
#if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||||
(*m_torrent->session().m_logger) << "*** CONNECTION FAILED '"
|
(*m_torrent->session().m_logger) << "*** CONNECTION FAILED '"
|
||||||
<< e.what() << "'\n";
|
<< e.what() << "'\n";
|
||||||
#endif
|
#endif
|
||||||
|
@ -1377,7 +1402,7 @@ namespace libtorrent
|
||||||
iterator p = find_disconnect_candidate();
|
iterator p = find_disconnect_candidate();
|
||||||
if (p == m_peers.end())
|
if (p == m_peers.end())
|
||||||
return false;
|
return false;
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING)
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||||
(*p->second.connection->m_logger) << "*** CLOSING CONNECTION 'too many connections'\n";
|
(*p->second.connection->m_logger) << "*** CLOSING CONNECTION 'too many connections'\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "libtorrent/torrent_info.hpp"
|
#include "libtorrent/torrent_info.hpp"
|
||||||
#include "libtorrent/escape_string.hpp"
|
#include "libtorrent/escape_string.hpp"
|
||||||
#include "libtorrent/kademlia/node_id.hpp"
|
#include "libtorrent/kademlia/node_id.hpp"
|
||||||
|
#include "libtorrent/broadcast_socket.hpp"
|
||||||
|
|
||||||
#include <boost/tuple/tuple.hpp>
|
#include <boost/tuple/tuple.hpp>
|
||||||
#include <boost/tuple/tuple_comparison.hpp>
|
#include <boost/tuple/tuple_comparison.hpp>
|
||||||
|
@ -367,6 +368,16 @@ int test_main()
|
||||||
h2 = sha1_hash(" ");
|
h2 = sha1_hash(" ");
|
||||||
TEST_CHECK(h2 == boost::lexical_cast<sha1_hash>("2020202020202020202020202020202020202020"));
|
TEST_CHECK(h2 == boost::lexical_cast<sha1_hash>("2020202020202020202020202020202020202020"));
|
||||||
|
|
||||||
|
// CIDR distance test
|
||||||
|
h1 = boost::lexical_cast<sha1_hash>("0123456789abcdef01232456789abcdef0123456");
|
||||||
|
h2 = boost::lexical_cast<sha1_hash>("0123456789abcdef01232456789abcdef0123456");
|
||||||
|
TEST_CHECK(common_bits(&h1[0], &h2[0], 20) == 160);
|
||||||
|
h2 = boost::lexical_cast<sha1_hash>("0120456789abcdef01232456789abcdef0123456");
|
||||||
|
TEST_CHECK(common_bits(&h1[0], &h2[0], 20) == 14);
|
||||||
|
h2 = boost::lexical_cast<sha1_hash>("012f456789abcdef01232456789abcdef0123456");
|
||||||
|
TEST_CHECK(common_bits(&h1[0], &h2[0], 20) == 12);
|
||||||
|
h2 = boost::lexical_cast<sha1_hash>("0123456789abcdef11232456789abcdef0123456");
|
||||||
|
TEST_CHECK(common_bits(&h1[0], &h2[0], 20) == 16 * 4 + 3);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue