diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp index 669187d61..2162cf51c 100644 --- a/include/libtorrent/peer_connection.hpp +++ b/include/libtorrent/peer_connection.hpp @@ -202,8 +202,6 @@ namespace libtorrent void set_upload_only(bool u) { m_upload_only = u; } bool upload_only() const { return m_upload_only; } - bool has_timed_out() const; - // will send a keep-alive message to the peer void keep_alive(); diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 0b842a8f3..06d97245e 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -2505,8 +2505,87 @@ namespace libtorrent { (*i)->tick(); } + if (is_disconnecting()) return; #endif + // if the peer hasn't said a thing for a certain + // time, it is considered to have timed out + time_duration d; + d = now - m_last_receive; + if (d > seconds(m_timeout) && !m_connecting) + { +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_logger) << time_now_string() << " *** LAST ACTIVITY [ " + << total_seconds(d) << " seconds ago ] ***\n"; +#endif + disconnect("timed out: inactivity"); + return; + } + + // do not stall waiting for a handshake + if (!m_connecting + && in_handshake() + && d > seconds(m_ses.settings().handshake_timeout)) + { +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_logger) << time_now_string() << " *** NO HANDSHAKE [ waited " + << total_seconds(d) << " seconds ] ***\n"; +#endif + disconnect("timed out: no hand shake"); + return; + } + + // disconnect peers that we unchoked, but + // they didn't send a request within 20 seconds. + // but only if we're a seed + d = now - (std::max)(m_last_unchoke, m_last_incoming_request); + if (!m_connecting + && m_requests.empty() + && !m_choked + && m_peer_interested + && t && t->is_finished() + && d > seconds(20)) + { +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_logger) << time_now_string() << " *** NO REQUEST [ t: " + << total_seconds(d) << " ] ***\n"; +#endif + disconnect("timed out: no request when unchoked"); + return; + } + + // if the peer hasn't become interested and we haven't + // become interested in the peer for 10 minutes, it + // has also timed out. + time_duration d1; + time_duration d2; + d1 = now - m_became_uninterested; + d2 = now - m_became_uninteresting; + time_duration time_limit = seconds( + m_ses.settings().inactivity_timeout); + + // don't bother disconnect peers we haven't been interested + // in (and that hasn't been interested in us) for a while + // unless we have used up all our connection slots + if (!m_interesting + && !m_peer_interested + && d1 > time_limit + && d2 > time_limit + && (m_ses.num_connections() >= m_ses.max_connections() + || (t && t->num_peers() >= t->max_connections()))) + { +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_logger) << time_now_string() << " *** MUTUAL NO INTEREST [ " + "t1: " << total_seconds(d1) << " | " + "t2: " << total_seconds(d2) << " ] ***\n"; +#endif + disconnect("timed out: no interest"); + return; + } + + // if we haven't sent something in too long, send a keep-alive + keep_alive(); + m_ignore_bandwidth_limits = m_ses.settings().ignore_limits_on_local_network && on_local_network(); @@ -3521,94 +3600,6 @@ namespace libtorrent } #endif - bool peer_connection::has_timed_out() const - { - // TODO: the timeout should be called by an event - INVARIANT_CHECK; - - ptime now(time_now()); - - // if the socket is still connecting, don't - // consider it timed out. Because Windows XP SP2 - // may delay connection attempts. - if (m_connecting) return false; - - // if the peer hasn't said a thing for a certain - // time, it is considered to have timed out - time_duration d; - d = now - m_last_receive; - if (d > seconds(m_timeout)) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << time_now_string() << " *** LAST ACTIVITY [ " - << total_seconds(d) << " seconds ago ] ***\n"; -#endif - return true; - } - - // do not stall waiting for a handshake - if (in_handshake() && d > seconds(m_ses.settings().handshake_timeout)) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << time_now_string() << " *** NO HANDSHAKE [ waited " - << total_seconds(d) << " seconds ] ***\n"; -#endif - return true; - } - - // disconnect peers that we unchoked, but - // they didn't send a request within 20 seconds. - // but only if we're a seed - boost::shared_ptr t = m_torrent.lock(); - d = now - (std::max)(m_last_unchoke, m_last_incoming_request); - if (m_requests.empty() - && !m_choked - && m_peer_interested - && t && t->is_finished() - && d > seconds(20)) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << time_now_string() << " *** NO REQUEST [ t: " - << total_seconds(d) << " ] ***\n"; -#endif - return true; - } - - // TODO: as long as we have less than 95% of the - // global (or local) connection limit, connections should - // never time out for another reason - - // if the peer hasn't become interested and we haven't - // become interested in the peer for 10 minutes, it - // has also timed out. - time_duration d1; - time_duration d2; - d1 = now - m_became_uninterested; - d2 = now - m_became_uninteresting; - time_duration time_limit = seconds( - m_ses.settings().inactivity_timeout); - - // don't bother disconnect peers we haven't been interested - // in (and that hasn't been interested in us) for a while - // unless we have used up all our connection slots - if (!m_interesting - && !m_peer_interested - && d1 > time_limit - && d2 > time_limit - && (m_ses.num_connections() >= m_ses.max_connections() - || (t && t->num_peers() >= t->max_connections()))) - { -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << time_now_string() << " *** MUTUAL NO INTEREST [ " - "t1: " << total_seconds(d1) << " | " - "t2: " << total_seconds(d2) << " ] ***\n"; -#endif - return true; - } - - return false; - } - peer_connection::peer_speed_t peer_connection::peer_speed() { shared_ptr t = m_torrent.lock(); diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 59d1e65a6..af16b06b4 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -1207,32 +1207,6 @@ namespace aux { } } - // do the second_tick() on each connection - // this will update their statistics (download and upload speeds) - // also purge sockets that have timed out - // and keep sockets open by keeping them alive. - for (connection_map::iterator i = m_connections.begin(); - i != m_connections.end();) - { - // we need to do like this because j->second->disconnect() will - // erase the connection from the map we're iterating - connection_map::iterator j = i; - ++i; - // if this socket has timed out - // close it. - peer_connection& c = *j->get(); - if (c.has_timed_out()) - { -#if defined(TORRENT_VERBOSE_LOGGING) - (*c.m_logger) << "*** CONNECTION TIMED OUT\n"; -#endif - c.disconnect("timed out: inactive", 1); - continue; - } - - c.keep_alive(); - } - // -------------------------------------------------------------- // auto managed torrent // --------------------------------------------------------------