fixed problem with clashing connections when allowing multiple peers from the same IP

This commit is contained in:
Arvid Norberg 2007-09-19 06:05:14 +00:00
parent 60f9d1366a
commit abbe3c774f
3 changed files with 45 additions and 18 deletions

View File

@ -1952,7 +1952,6 @@ namespace libtorrent
} }
t->remove_peer(this); t->remove_peer(this);
m_torrent.reset(); m_torrent.reset();
} }
@ -2856,6 +2855,8 @@ namespace libtorrent
return; return;
} }
assert(t->connection_for(remote()) != 0 || m_in_constructor);
if (!m_in_constructor && t->connection_for(remote()) != this if (!m_in_constructor && t->connection_for(remote()) != this
&& !m_ses.settings().allow_multiple_connections_per_ip) && !m_ses.settings().allow_multiple_connections_per_ip)
{ {

View File

@ -138,28 +138,28 @@ namespace
return free_upload; return free_upload;
} }
struct match_peer_ip struct match_peer_address
{ {
match_peer_ip(address const& ip) match_peer_address(address const& addr)
: m_ip(ip) : m_addr(addr)
{} {}
bool operator()(policy::peer const& p) const bool operator()(policy::peer const& p) const
{ return p.ip.address() == m_ip; } { return p.ip.address() == m_addr; }
address const& m_ip; address const& m_addr;
}; };
struct match_peer_id struct match_peer_endpoint
{ {
match_peer_id(peer_id const& id_) match_peer_endpoint(tcp::endpoint const& ep)
: m_id(id_) : m_ep(ep)
{} {}
bool operator()(policy::peer const& p) const bool operator()(policy::peer const& p) const
{ return p.connection && p.connection->pid() == m_id; } { return p.ip == m_ep; }
peer_id const& m_id; tcp::endpoint const& m_ep;
}; };
struct match_peer_connection struct match_peer_connection
@ -939,7 +939,7 @@ namespace libtorrent
i = std::find_if( i = std::find_if(
m_peers.begin() m_peers.begin()
, m_peers.end() , m_peers.end()
, match_peer_ip(c.remote().address())); , match_peer_address(c.remote().address()));
} }
if (i != m_peers.end()) if (i != m_peers.end())
@ -1029,14 +1029,14 @@ namespace libtorrent
i = std::find_if( i = std::find_if(
m_peers.begin() m_peers.begin()
, m_peers.end() , m_peers.end()
, match_peer_id(pid)); , match_peer_endpoint(remote));
} }
else else
{ {
i = std::find_if( i = std::find_if(
m_peers.begin() m_peers.begin()
, m_peers.end() , m_peers.end()
, match_peer_ip(remote.address())); , match_peer_address(remote.address()));
} }
if (i == m_peers.end()) if (i == m_peers.end())
@ -1291,9 +1291,15 @@ namespace libtorrent
try try
{ {
INVARIANT_CHECK;
p->connected = time_now(); p->connected = time_now();
p->connection = m_torrent->connect_to_peer(&*p); p->connection = m_torrent->connect_to_peer(&*p);
if (p->connection == 0) return false; assert(p->connection == m_torrent->connection_for(p->ip));
if (p->connection == 0)
{
++p->failcount;
return false;
}
p->connection->add_stat(p->prev_amount_download, p->prev_amount_upload); p->connection->add_stat(p->prev_amount_download, p->prev_amount_upload);
p->prev_amount_download = 0; p->prev_amount_download = 0;
p->prev_amount_upload = 0; p->prev_amount_upload = 0;
@ -1305,6 +1311,7 @@ namespace libtorrent
(*m_torrent->session().m_logger) << "*** CONNECTION FAILED '" (*m_torrent->session().m_logger) << "*** CONNECTION FAILED '"
<< e.what() << "'\n"; << e.what() << "'\n";
#endif #endif
std::cerr << e.what() << std::endl;
++p->failcount; ++p->failcount;
return false; return false;
} }
@ -1402,15 +1409,22 @@ namespace libtorrent
int nonempty_connections = 0; int nonempty_connections = 0;
std::set<address> unique_test; std::set<address> unique_test;
std::set<tcp::endpoint> unique_test2;
for (const_iterator i = m_peers.begin(); for (const_iterator i = m_peers.begin();
i != m_peers.end(); ++i) i != m_peers.end(); ++i)
{ {
peer const& p = *i; peer const& p = *i;
if (!m_torrent->settings().allow_multiple_connections_per_ip) if (!m_torrent->settings().allow_multiple_connections_per_ip)
assert(unique_test.find(p.ip.address()) == unique_test.end()); assert(unique_test.find(p.ip.address()) == unique_test.end());
assert(unique_test2.find(p.ip) == unique_test2.end());
unique_test.insert(p.ip.address()); unique_test.insert(p.ip.address());
unique_test2.insert(p.ip);
++total_connections; ++total_connections;
if (!p.connection) continue; if (!p.connection)
{
assert(m_torrent->connection_for(p.ip) == 0);
continue;
}
if (!m_torrent->settings().allow_multiple_connections_per_ip) if (!m_torrent->settings().allow_multiple_connections_per_ip)
{ {
std::vector<peer_connection*> conns; std::vector<peer_connection*> conns;

View File

@ -1653,6 +1653,7 @@ namespace libtorrent
assert(m_connections.find(a) == m_connections.end()); assert(m_connections.find(a) == m_connections.end());
// add the newly connected peer to this torrent's peer list // add the newly connected peer to this torrent's peer list
assert(m_connections.find(a) == m_connections.end());
m_connections.insert( m_connections.insert(
std::make_pair(a, boost::get_pointer(c))); std::make_pair(a, boost::get_pointer(c)));
m_ses.m_connections.insert(std::make_pair(s, c)); m_ses.m_connections.insert(std::make_pair(s, c));
@ -1669,8 +1670,8 @@ namespace libtorrent
#endif #endif
// TODO: post an error alert! // TODO: post an error alert!
std::map<tcp::endpoint, peer_connection*>::iterator i = m_connections.find(a); // std::map<tcp::endpoint, peer_connection*>::iterator i = m_connections.find(a);
if (i != m_connections.end()) m_connections.erase(i); // if (i != m_connections.end()) m_connections.erase(i);
m_ses.connection_failed(s, a, e.what()); m_ses.connection_failed(s, a, e.what());
c->disconnect(); c->disconnect();
} }
@ -1857,6 +1858,8 @@ namespace libtorrent
try try
{ {
assert(m_connections.find(a) == m_connections.end());
// add the newly connected peer to this torrent's peer list // add the newly connected peer to this torrent's peer list
m_connections.insert( m_connections.insert(
std::make_pair(a, boost::get_pointer(c))); std::make_pair(a, boost::get_pointer(c)));
@ -1869,6 +1872,7 @@ namespace libtorrent
} }
catch (std::exception& e) catch (std::exception& e)
{ {
assert(false);
// TODO: post an error alert! // TODO: post an error alert!
std::map<tcp::endpoint, peer_connection*>::iterator i = m_connections.find(a); std::map<tcp::endpoint, peer_connection*>::iterator i = m_connections.find(a);
if (i != m_connections.end()) m_connections.erase(i); if (i != m_connections.end()) m_connections.erase(i);
@ -1925,6 +1929,7 @@ namespace libtorrent
= m_connections.find(p->remote()); = m_connections.find(p->remote());
if (c != m_connections.end()) if (c != m_connections.end())
{ {
assert(p != c->second);
// we already have a peer_connection to this ip. // we already have a peer_connection to this ip.
// It may currently be waiting for completing a // It may currently be waiting for completing a
// connection attempt that might fail. So, // connection attempt that might fail. So,
@ -1948,6 +1953,7 @@ namespace libtorrent
throw protocol_error("session is closing"); throw protocol_error("session is closing");
} }
assert(m_connections.find(p->remote()) == m_connections.end());
peer_iterator ci = m_connections.insert( peer_iterator ci = m_connections.insert(
std::make_pair(p->remote(), p)).first; std::make_pair(p->remote(), p)).first;
try try
@ -2408,6 +2414,12 @@ namespace libtorrent
assert(m_abort || m_have_pieces.empty()); assert(m_abort || m_have_pieces.empty());
} }
/* for (policy::const_iterator i = m_policy->begin_peer()
, end(m_policy->end_peer()); i != end; ++i)
{
assert(i->connection == const_cast<torrent*>(this)->connection_for(i->ip));
}
*/
size_type total_done = quantized_bytes_done(); size_type total_done = quantized_bytes_done();
if (m_torrent_file->is_valid()) if (m_torrent_file->is_valid())
{ {