don't let hung outgoing connection attempts block incoming connections

This commit is contained in:
Arvid Norberg 2012-01-21 09:05:34 +00:00
parent 5c8d476022
commit 7f90a241b6
5 changed files with 96 additions and 11 deletions

View File

@ -1,3 +1,4 @@
* don't let hung outgoing connection attempts block incoming connections
* improve SSL torrent support by using SNI and a single SSL listen socket * improve SSL torrent support by using SNI and a single SSL listen socket
* improved peer exchange performance by sharing incoming connections which advertize listen port * improved peer exchange performance by sharing incoming connections which advertize listen port
* deprecate set_ratio(), and per-peer rate limits * deprecate set_ratio(), and per-peer rate limits

View File

@ -955,6 +955,12 @@ namespace libtorrent
public: public:
#endif #endif
std::set<peer_connection*> m_connections; std::set<peer_connection*> m_connections;
// of all peers in m_connections, this is the number
// of peers that are outgoing and still waiting to
// complete the connection. This is used to possibly
// kick out these connections when we get incoming
// connections (if we've reached the connection limit)
int m_num_connecting;
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
private: private:
#endif #endif

View File

@ -200,6 +200,14 @@ namespace libtorrent
, m_received_in_piece(0) , m_received_in_piece(0)
#endif #endif
{ {
boost::shared_ptr<torrent> t = m_torrent.lock();
// if t is NULL, we better not be connecting, since
// we can't decrement the connecting counter
TORRENT_ASSERT(t || !m_connecting);
if (m_connecting && t)
{
++t->m_num_connecting;
}
m_est_reciprocation_rate = m_ses.m_settings.default_est_reciprocation_rate; m_est_reciprocation_rate = m_ses.m_settings.default_est_reciprocation_rate;
#if TORRENT_USE_I2P #if TORRENT_USE_I2P
@ -347,6 +355,14 @@ namespace libtorrent
, m_received_in_piece(0) , m_received_in_piece(0)
#endif #endif
{ {
boost::shared_ptr<torrent> t = m_torrent.lock();
// if t is NULL, we better not be connecting, since
// we can't decrement the connecting counter
TORRENT_ASSERT(t || !m_connecting);
if (m_connecting && t)
{
++t->m_num_connecting;
}
m_est_reciprocation_rate = m_ses.m_settings.default_est_reciprocation_rate; m_est_reciprocation_rate = m_ses.m_settings.default_est_reciprocation_rate;
#if TORRENT_USE_I2P #if TORRENT_USE_I2P
@ -910,6 +926,22 @@ namespace libtorrent
TORRENT_ASSERT(m_disconnecting); TORRENT_ASSERT(m_disconnecting);
TORRENT_ASSERT(m_disconnect_started); TORRENT_ASSERT(m_disconnect_started);
// defensive
boost::shared_ptr<torrent> t = m_torrent.lock();
// if t is NULL, we better not be connecting, since
// we can't decrement the connecting counter
TORRENT_ASSERT(t || !m_connecting);
// we should really have dealt with this already
TORRENT_ASSERT(!m_connecting);
if (m_connecting && t)
{
TORRENT_ASSERT(t->m_num_connecting > 0);
--t->m_num_connecting;
m_connecting = false;
}
m_disk_recv_buffer_size = 0; m_disk_recv_buffer_size = 0;
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
@ -928,8 +960,6 @@ namespace libtorrent
TORRENT_ASSERT(!i->second->has_peer(this)); TORRENT_ASSERT(!i->second->has_peer(this));
if (m_peer_info) if (m_peer_info)
TORRENT_ASSERT(m_peer_info->connection == 0); TORRENT_ASSERT(m_peer_info->connection == 0);
boost::shared_ptr<torrent> t = m_torrent.lock();
#endif #endif
} }
@ -3396,10 +3426,17 @@ namespace libtorrent
TORRENT_ASSERT(m_connecting); TORRENT_ASSERT(m_connecting);
boost::shared_ptr<torrent> t = m_torrent.lock();
if (m_connecting)
{
TORRENT_ASSERT(t->m_num_connecting > 0);
--t->m_num_connecting;
m_connecting = false;
}
if (m_connection_ticket != -1) if (m_connection_ticket != -1)
{ {
m_ses.m_half_open.done(m_connection_ticket); m_ses.m_half_open.done(m_connection_ticket);
m_connecting = false;
} }
// a connection attempt using uTP just failed // a connection attempt using uTP just failed
@ -3523,13 +3560,19 @@ namespace libtorrent
m_channel_state[download_channel] &= ~peer_info::bw_disk; m_channel_state[download_channel] &= ~peer_info::bw_disk;
} }
if (m_connecting && m_connection_ticket >= 0) boost::shared_ptr<torrent> t = m_torrent.lock();
if (m_connecting)
{
TORRENT_ASSERT(t->m_num_connecting > 0);
--t->m_num_connecting;
m_connecting = false;
}
if (m_connection_ticket >= 0)
{ {
m_ses.m_half_open.done(m_connection_ticket); m_ses.m_half_open.done(m_connection_ticket);
m_connection_ticket = -1; m_connection_ticket = -1;
} }
boost::shared_ptr<torrent> t = m_torrent.lock();
torrent_handle handle; torrent_handle handle;
if (t) handle = t->get_handle(); if (t) handle = t->get_handle();
@ -4052,7 +4095,14 @@ namespace libtorrent
if (!t || m_disconnecting) if (!t || m_disconnecting)
{ {
m_ses.m_half_open.done(m_connection_ticket); m_ses.m_half_open.done(m_connection_ticket);
if (m_connection_ticket >= -1) m_connection_ticket = -1;
TORRENT_ASSERT(t || !m_connecting);
if (m_connecting && t)
{
TORRENT_ASSERT(t->m_num_connecting > 0);
--t->m_num_connecting;
m_connecting = false; m_connecting = false;
}
disconnect(errors::torrent_aborted); disconnect(errors::torrent_aborted);
return; return;
} }
@ -5427,7 +5477,16 @@ namespace libtorrent
return; return;
} }
// if t is NULL, we better not be connecting, since
// we can't decrement the connecting counter
boost::shared_ptr<torrent> t = m_torrent.lock();
TORRENT_ASSERT(t || !m_connecting);
if (m_connecting && t)
{
TORRENT_ASSERT(t->m_num_connecting > 0);
--t->m_num_connecting;
m_connecting = false; m_connecting = false;
}
m_ses.m_half_open.done(m_connection_ticket); m_ses.m_half_open.done(m_connection_ticket);
if (m_disconnecting) return; if (m_disconnecting) return;
@ -5469,7 +5528,6 @@ namespace libtorrent
{ {
// if the remote endpoint is the same as the local endpoint, we're connected // if the remote endpoint is the same as the local endpoint, we're connected
// to ourselves // to ourselves
boost::shared_ptr<torrent> t = m_torrent.lock();
if (m_peer_info && t) t->get_policy().ban_peer(m_peer_info); if (m_peer_info && t) t->get_policy().ban_peer(m_peer_info);
disconnect(errors::self_connection, 1); disconnect(errors::self_connection, 1);
return; return;

View File

@ -352,6 +352,7 @@ namespace libtorrent
, m_total_downloaded(0) , m_total_downloaded(0)
, m_started(time_now()) , m_started(time_now())
, m_storage(0) , m_storage(0)
, m_num_connecting(0)
, m_tracker_timer(ses.m_io_service) , m_tracker_timer(ses.m_io_service)
, m_ses(ses) , m_ses(ses)
, m_trackerid(p.trackerid) , m_trackerid(p.trackerid)
@ -5648,11 +5649,30 @@ namespace libtorrent
} }
if (m_connections.size() >= m_max_connections) if (m_connections.size() >= m_max_connections)
{
// if more than 10% of the connections are outgoing
// connection attempts that haven't completed yet,
// disconnect one of them and let this incoming
// connection through.
if (m_num_connecting < m_max_connections / 10)
{ {
p->disconnect(errors::too_many_connections); p->disconnect(errors::too_many_connections);
return false; return false;
} }
// find one of the connecting peers and disconnect it
// TODO: ideally, we would disconnect the oldest connection
// i.e. the one that has waited the longest to connect.
for (std::set<peer_connection*>::iterator i = m_connections.begin()
, end(m_connections.end()); i != end; ++i)
{
peer_connection* p = *i;
if (!p->is_connecting()) continue;
p->disconnect(errors::too_many_connections);
break;
}
}
TORRENT_TRY TORRENT_TRY
{ {
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS