diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp index 99e195b66..c4ca2ecae 100644 --- a/include/libtorrent/peer_connection.hpp +++ b/include/libtorrent/peer_connection.hpp @@ -601,6 +601,10 @@ namespace libtorrent size_type downloaded_since_unchoke() const { return m_statistics.total_payload_download() - m_downloaded_at_last_unchoke; } + // called when the disk write buffer is drained again, and we can + // start downloading payload again + void on_disk(); + enum sync_t { read_async, read_sync }; void setup_receive(sync_t sync = read_sync); diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 7d9fbfaef..642ffea96 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -4524,12 +4524,20 @@ namespace libtorrent m_channel_state[upload_channel] = peer_info::bw_network; } + void peer_connection::on_disk() + { + if (m_channel_state[download_channel] != peer_info::bw_disk) return; + boost::intrusive_ptr me(this); + + m_channel_state[download_channel] = peer_info::bw_idle; + setup_receive(); + } + void peer_connection::setup_receive(sync_t sync) { INVARIANT_CHECK; - if (m_channel_state[download_channel] != peer_info::bw_idle - && m_channel_state[download_channel] != peer_info::bw_disk) return; + if (m_channel_state[download_channel] != peer_info::bw_idle) return; shared_ptr t = m_torrent.lock(); @@ -4864,6 +4872,13 @@ namespace libtorrent , std::size_t bytes_transferred) { TORRENT_ASSERT(m_ses.is_network_thread()); + + // keep ourselves alive in until this function exits in + // case we disconnect + // this needs to be created before the invariant check, + // to keep the object alive through the exit check + boost::intrusive_ptr me(self()); + INVARIANT_CHECK; #ifdef TORRENT_VERBOSE_LOGGING @@ -4873,10 +4888,6 @@ namespace libtorrent #if defined TORRENT_ASIO_DEBUGGING complete_async("peer_connection::on_receive_data"); #endif - // keep ourselves alive in until this function exits in - // case we disconnect - boost::intrusive_ptr me(self()); - TORRENT_ASSERT(m_channel_state[download_channel] == peer_info::bw_network); m_channel_state[download_channel] = peer_info::bw_idle; diff --git a/src/session_impl.cpp b/src/session_impl.cpp index c4e4720c1..0b656d07a 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -2217,11 +2217,10 @@ namespace aux { TORRENT_ASSERT(p->is_disconnecting()); if (!p->is_choked() && !p->ignore_unchoke_slots()) --m_num_unchoked; -// connection_map::iterator i = std::lower_bound(m_connections.begin(), m_connections.end() -// , p, boost::bind(&boost::intrusive_ptr::get, _1) < p); -// if (i->get() != p) i == m_connections.end(); - connection_map::iterator i = std::find_if(m_connections.begin(), m_connections.end() - , boost::bind(&boost::intrusive_ptr::get, _1) == p); + TORRENT_ASSERT(p->refcount() > 0); + + boost::intrusive_ptr sp((peer_connection*)p); + connection_map::iterator i = m_connections.find(sp); if (i != m_connections.end()) m_connections.erase(i); } @@ -2295,7 +2294,7 @@ namespace aux { { // setup_receive() may disconnect the connection // and clear it out from the m_connections list - (*i)->setup_receive(); + (*i)->on_disk(); } } @@ -2427,8 +2426,10 @@ namespace aux { else { if (num_tcp_peers == 0) num_tcp_peers = 1; - int upload_rate = (std::max)(m_stat.upload_rate(), 20000); - int download_rate = (std::max)(m_stat.download_rate(), 20000); + // these are 64 bits since they are multiplied by the number + // of peers, which otherwise might overflow an int + boost::uint64_t upload_rate = (std::max)(m_stat.upload_rate(), 20000); + boost::uint64_t download_rate = (std::max)(m_stat.download_rate(), 20000); if (m_upload_channel.throttle()) upload_rate = m_upload_channel.throttle(); if (m_download_channel.throttle()) download_rate = m_download_channel.throttle(); @@ -4316,8 +4317,6 @@ namespace aux { void session_impl::update_connections_limit() { - INVARIANT_CHECK; - if (m_settings.connections_limit <= 0) { m_settings.connections_limit = (std::numeric_limits::max)();