fix issues introduced with connection ordering

This commit is contained in:
Arvid Norberg 2013-01-02 07:48:09 +00:00
parent 970ddba29b
commit 5afa8c88b9
3 changed files with 55 additions and 20 deletions

View File

@ -118,7 +118,9 @@ namespace libtorrent
address external_ip::external_address(address const& ip) const
{
return m_vote_group[ip.is_v6()].external_address();
address ext = m_vote_group[ip.is_v6()].external_address();
if (ip.is_v6() && ext == address_v4()) return address_v6();
return ext;
}
}

View File

@ -4830,11 +4830,27 @@ retry:
return boost::weak_ptr<torrent>();
}
// returns true if lhs is a better disconnect candidate than rhs
bool compare_disconnect_torrent(session_impl::torrent_map::value_type const& lhs
, session_impl::torrent_map::value_type const& rhs)
{
// a torrent with 0 peers is never a good disconnect candidate
// since there's nothing to disconnect
if ((lhs.second->num_peers() == 0) != (lhs.second->num_peers() == 0))
return lhs.second->num_peers() != 0;
// other than that, always prefer to disconnect peers from seeding torrents
// in order to not harm downloading ones
if (lhs.second->is_seed() != rhs.second->is_seed())
return lhs.second->is_seed();
return lhs.second->num_peers() > rhs.second->num_peers();
}
boost::weak_ptr<torrent> session_impl::find_disconnect_candidate_torrent()
{
aux::session_impl::torrent_map::iterator i = std::max_element(m_torrents.begin(), m_torrents.end()
, boost::bind(&torrent::num_peers, boost::bind(&session_impl::torrent_map::value_type::second, _1))
< boost::bind(&torrent::num_peers, boost::bind(&session_impl::torrent_map::value_type::second, _2)));
aux::session_impl::torrent_map::iterator i = std::min_element(m_torrents.begin(), m_torrents.end()
, boost::bind(&compare_disconnect_torrent, _1, _2));
TORRENT_ASSERT(i != m_torrents.end());
if (i == m_torrents.end()) return boost::shared_ptr<torrent>();

View File

@ -4328,7 +4328,8 @@ namespace libtorrent
if (ready_for_connections())
{
TORRENT_ASSERT(p->associated_torrent().lock().get() == this);
TORRENT_ASSERT(p->associated_torrent().lock().get() == NULL
|| p->associated_torrent().lock().get() == this);
if (p->is_seed())
{
@ -5890,6 +5891,8 @@ namespace libtorrent
return false;
}
bool maybe_replace_peer = false;
if (m_connections.size() >= m_max_connections)
{
// if more than 10% of the connections are outgoing
@ -5923,21 +5926,7 @@ namespace libtorrent
}
else
{
// now, find the lowest rank peer and disconnect that
// if it's lower rank than the incoming connection
peer_connection* peer = find_lowest_ranking_peer();
// TODO: if peer is a really good peer, maybe we shouldn't disconnect it
if (peer && peer->peer_rank() < p->peer_rank())
{
peer->disconnect(errors::too_many_connections);
p->peer_disconnected_other();
}
else
{
p->disconnect(errors::too_many_connections);
return false;
}
maybe_replace_peer = true;
}
}
@ -5979,6 +5968,34 @@ namespace libtorrent
TORRENT_ASSERT(p->remote() == p->get_socket()->remote_endpoint(ec) || ec);
#endif
TORRENT_ASSERT(p->peer_info_struct() != NULL);
// we need to do this after we've added the peer to the policy
// since that's when the peer is assigned its peer_info object,
// which holds the rank
if (maybe_replace_peer)
{
// now, find the lowest rank peer and disconnect that
// if it's lower rank than the incoming connection
peer_connection* peer = find_lowest_ranking_peer();
// TODO: if peer is a really good peer, maybe we shouldn't disconnect it
if (peer && peer->peer_rank() < p->peer_rank())
{
peer->disconnect(errors::too_many_connections);
p->peer_disconnected_other();
}
else
{
p->disconnect(errors::too_many_connections);
// we have to do this here because from the peer's point of
// it wasn't really attached to the torrent, but we do need
// to let policy know we're removing it
remove_peer(p);
return false;
}
}
#if defined TORRENT_DEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS
m_policy.check_invariant();
#endif