diff --git a/libtorrent/bindings/python/src/docstrings.cpp b/libtorrent/bindings/python/src/docstrings.cpp index f2aa7bfd0..0fa001f39 100755 --- a/libtorrent/bindings/python/src/docstrings.cpp +++ b/libtorrent/bindings/python/src/docstrings.cpp @@ -177,8 +177,6 @@ char const* session_start_natpmp_doc = ""; char const* session_stop_natpmp_doc = ""; -char const* session_wait_for_alert_doc = - ""; // -- alert ----------------------------------------------------------------- diff --git a/libtorrent/bindings/python/src/session.cpp b/libtorrent/bindings/python/src/session.cpp index 1b9f0ffc3..481348730 100755 --- a/libtorrent/bindings/python/src/session.cpp +++ b/libtorrent/bindings/python/src/session.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include "gil.hpp" @@ -57,7 +56,6 @@ extern char const* session_stop_lsd_doc; extern char const* session_stop_upnp_doc; extern char const* session_start_natpmp_doc; extern char const* session_stop_natpmp_doc; -extern char const* session_wait_for_alert_doc; namespace { @@ -250,7 +248,6 @@ void bind_session() .def("stop_lsd", allow_threads(&session::stop_lsd), session_stop_lsd_doc) .def("start_natpmp", allow_threads(&session::start_natpmp), session_start_natpmp_doc) .def("stop_natpmp", allow_threads(&session::stop_natpmp), session_stop_natpmp_doc) - .def("wait_for_alert", allow_threads(&session::wait_for_alert), session_wait_for_alert_doc) ; register_ptr_to_python >(); diff --git a/libtorrent/include/libtorrent/alert.hpp b/libtorrent/include/libtorrent/alert.hpp index 896443aaa..ab8065f1f 100755 --- a/libtorrent/include/libtorrent/alert.hpp +++ b/libtorrent/include/libtorrent/alert.hpp @@ -100,7 +100,7 @@ namespace libtorrent { void set_severity(alert::severity_t severity); bool should_post(alert::severity_t severity) const; - std::auto_ptr wait_for_alert(time_duration max_wait); + alert const* wait_for_alert(time_duration max_wait); private: std::queue m_alerts; diff --git a/libtorrent/include/libtorrent/aux_/session_impl.hpp b/libtorrent/include/libtorrent/aux_/session_impl.hpp index 803d78e00..cf627c70b 100644 --- a/libtorrent/include/libtorrent/aux_/session_impl.hpp +++ b/libtorrent/include/libtorrent/aux_/session_impl.hpp @@ -280,7 +280,7 @@ namespace libtorrent void set_severity_level(alert::severity_t s); std::auto_ptr pop_alert(); - std::auto_ptr wait_for_alert(time_duration max_wait); + alert const* wait_for_alert(time_duration max_wait); int upload_rate_limit() const; int download_rate_limit() const; diff --git a/libtorrent/include/libtorrent/bandwidth_manager.hpp b/libtorrent/include/libtorrent/bandwidth_manager.hpp index ef132543f..da251cf4b 100644 --- a/libtorrent/include/libtorrent/bandwidth_manager.hpp +++ b/libtorrent/include/libtorrent/bandwidth_manager.hpp @@ -111,7 +111,7 @@ struct bandwidth_limit void assign(int amount) throw() { - TORRENT_ASSERT(amount > 0); + TORRENT_ASSERT(amount >= 0); m_current_rate += amount; m_quota_left += amount; } @@ -225,8 +225,14 @@ struct bandwidth_manager } #endif - TORRENT_ASSERT(peer->max_assignable_bandwidth(m_channel) > 0); boost::shared_ptr t = peer->associated_torrent().lock(); + + if (peer->max_assignable_bandwidth(m_channel) == 0) + { + t->expire_bandwidth(m_channel, blk); + peer->assign_bandwidth(m_channel, 0); + return; + } m_queue.push_back(bw_queue_entry(peer, blk, non_prioritized)); if (!non_prioritized) { @@ -389,6 +395,7 @@ private: if (max_assignable == 0) { t->expire_bandwidth(m_channel, qe.max_block_size); + qe.peer->assign_bandwidth(m_channel, 0); TORRENT_ASSERT(amount == limit - m_current_quota); continue; } @@ -430,7 +437,7 @@ private: if (block_size > qe.max_block_size) block_size = qe.max_block_size; #ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT - std::cerr << " block_size = " << block_size << " amount = " << amount << std::endl; + std::cerr << " block_size = " << block_size << " amount = " << amount << std::endl; #endif if (amount < block_size / 2) { diff --git a/libtorrent/include/libtorrent/disk_io_thread.hpp b/libtorrent/include/libtorrent/disk_io_thread.hpp index b93ea8b75..a77522356 100644 --- a/libtorrent/include/libtorrent/disk_io_thread.hpp +++ b/libtorrent/include/libtorrent/disk_io_thread.hpp @@ -124,7 +124,8 @@ namespace libtorrent private: - mutable boost::mutex m_mutex; + typedef boost::recursive_mutex mutex_t; + mutable mutex_t m_mutex; boost::condition m_signal; bool m_abort; std::deque m_jobs; diff --git a/libtorrent/include/libtorrent/kademlia/dht_tracker.hpp b/libtorrent/include/libtorrent/kademlia/dht_tracker.hpp index f61364707..c032c19d1 100644 --- a/libtorrent/include/libtorrent/kademlia/dht_tracker.hpp +++ b/libtorrent/include/libtorrent/kademlia/dht_tracker.hpp @@ -127,7 +127,20 @@ namespace libtorrent { namespace dht // used to resolve hostnames for nodes udp::resolver m_host_resolver; - + + // used to ignore abusive dht nodes + struct node_ban_entry + { + node_ban_entry(): count(0) {} + udp::endpoint src; + ptime limit; + int count; + }; + + enum { num_ban_nodes = 20 }; + + node_ban_entry m_ban_nodes[num_ban_nodes]; + // reference counter for intrusive_ptr mutable boost::detail::atomic_count m_refs; diff --git a/libtorrent/include/libtorrent/session.hpp b/libtorrent/include/libtorrent/session.hpp index b9a726fb8..d2ab6ab2e 100755 --- a/libtorrent/include/libtorrent/session.hpp +++ b/libtorrent/include/libtorrent/session.hpp @@ -265,7 +265,7 @@ namespace libtorrent std::auto_ptr pop_alert(); void set_severity_level(alert::severity_t s); - std::auto_ptr wait_for_alert(time_duration max_wait); + alert const* wait_for_alert(time_duration max_wait); connection_queue& get_connection_queue(); diff --git a/libtorrent/include/libtorrent/session_settings.hpp b/libtorrent/include/libtorrent/session_settings.hpp index df393692a..7cc7d26da 100644 --- a/libtorrent/include/libtorrent/session_settings.hpp +++ b/libtorrent/include/libtorrent/session_settings.hpp @@ -84,7 +84,7 @@ namespace libtorrent LIBTORRENT_VERSION) : user_agent(user_agent_) , tracker_completion_timeout(60) - , tracker_receive_timeout(20) + , tracker_receive_timeout(40) , stop_tracker_timeout(5) , tracker_maximum_response_length(1024*1024) , piece_timeout(10) diff --git a/libtorrent/include/libtorrent/time.hpp b/libtorrent/include/libtorrent/time.hpp index 4ab7a3819..ec1c0bce9 100644 --- a/libtorrent/include/libtorrent/time.hpp +++ b/libtorrent/include/libtorrent/time.hpp @@ -99,6 +99,7 @@ namespace libtorrent time_duration operator/(int rhs) const { return time_duration(diff / rhs); } explicit time_duration(boost::int64_t d) : diff(d) {} time_duration& operator-=(time_duration const& c) { diff -= c.diff; return *this; } + time_duration operator+(time_duration const& c) { return time_duration(diff + c.diff); } boost::int64_t diff; }; diff --git a/libtorrent/src/alert.cpp b/libtorrent/src/alert.cpp index 5b0f892f8..cb89147da 100755 --- a/libtorrent/src/alert.cpp +++ b/libtorrent/src/alert.cpp @@ -78,11 +78,11 @@ namespace libtorrent { } } - std::auto_ptr alert_manager::wait_for_alert(time_duration max_wait) + alert const* alert_manager::wait_for_alert(time_duration max_wait) { boost::mutex::scoped_lock lock(m_mutex); - if (!m_alerts.empty()) return std::auto_ptr(m_alerts.front()); + if (!m_alerts.empty()) return m_alerts.front(); int secs = total_seconds(max_wait); max_wait -= seconds(secs); @@ -96,10 +96,10 @@ namespace libtorrent { xt.sec += 1; } xt.nsec = nsec; - if (!m_condition.timed_wait(lock, xt)) return std::auto_ptr(NULL); + if (!m_condition.timed_wait(lock, xt)) return 0; TORRENT_ASSERT(!m_alerts.empty()); - if (m_alerts.empty()) return std::auto_ptr(NULL); - return std::auto_ptr(m_alerts.front()); + if (m_alerts.empty()) return 0; + return m_alerts.front(); } void alert_manager::post_alert(const alert& alert_) diff --git a/libtorrent/src/disk_io_thread.cpp b/libtorrent/src/disk_io_thread.cpp index a9446f664..e0fa982bc 100644 --- a/libtorrent/src/disk_io_thread.cpp +++ b/libtorrent/src/disk_io_thread.cpp @@ -62,7 +62,7 @@ namespace libtorrent disk_io_thread::~disk_io_thread() { - boost::mutex::scoped_lock l(m_mutex); + mutex_t::scoped_lock l(m_mutex); m_abort = true; m_signal.notify_all(); l.unlock(); @@ -74,7 +74,7 @@ namespace libtorrent disk_io_job disk_io_thread::find_job(boost::intrusive_ptr s , int action, int piece) const { - boost::mutex::scoped_lock l(m_mutex); + mutex_t::scoped_lock l(m_mutex); for (std::deque::const_iterator i = m_jobs.begin(); i != m_jobs.end(); ++i) { @@ -98,7 +98,7 @@ namespace libtorrent // aborts read operations void disk_io_thread::stop(boost::intrusive_ptr s) { - boost::mutex::scoped_lock l(m_mutex); + mutex_t::scoped_lock l(m_mutex); // read jobs are aborted, write and move jobs are syncronized for (std::deque::iterator i = m_jobs.begin(); i != m_jobs.end();) @@ -151,7 +151,7 @@ namespace libtorrent { TORRENT_ASSERT(!j.callback); TORRENT_ASSERT(j.storage); - boost::mutex::scoped_lock l(m_mutex); + mutex_t::scoped_lock l(m_mutex); std::deque::reverse_iterator i = m_jobs.rbegin(); if (j.action == disk_io_job::read) @@ -206,7 +206,7 @@ namespace libtorrent char* disk_io_thread::allocate_buffer() { - boost::mutex::scoped_lock l(m_mutex); + mutex_t::scoped_lock l(m_mutex); #ifdef TORRENT_STATS ++m_allocations; #endif @@ -215,7 +215,7 @@ namespace libtorrent void disk_io_thread::free_buffer(char* buf) { - boost::mutex::scoped_lock l(m_mutex); + mutex_t::scoped_lock l(m_mutex); #ifdef TORRENT_STATS --m_allocations; #endif @@ -229,7 +229,7 @@ namespace libtorrent #ifdef TORRENT_DISK_STATS m_log << log_time() << " idle" << std::endl; #endif - boost::mutex::scoped_lock l(m_mutex); + mutex_t::scoped_lock l(m_mutex); #ifndef NDEBUG m_current.action = (disk_io_job::action_t)-1; m_current.piece = -1; @@ -250,7 +250,7 @@ namespace libtorrent int ret = 0; - bool free_buffer = true; + bool free_current_buffer = true; try { TORRENT_ASSERT(j.storage); @@ -264,15 +264,10 @@ namespace libtorrent #ifdef TORRENT_DISK_STATS m_log << log_time() << " read " << j.buffer_size << std::endl; #endif - free_buffer = false; + free_current_buffer = false; if (j.buffer == 0) { - l.lock(); - j.buffer = (char*)m_pool.ordered_malloc(); -#ifdef TORRENT_STATS - ++m_allocations; -#endif - l.unlock(); + j.buffer = allocate_buffer(); TORRENT_ASSERT(j.buffer_size <= m_block_size); if (j.buffer == 0) { @@ -347,14 +342,7 @@ namespace libtorrent m_current.callback.clear(); #endif - if (j.buffer && free_buffer) - { - l.lock(); - m_pool.ordered_free(j.buffer); -#ifdef TORRENT_STATS - --m_allocations; -#endif - } + if (j.buffer && free_current_buffer) free_buffer(j.buffer); } } } diff --git a/libtorrent/src/http_connection.cpp b/libtorrent/src/http_connection.cpp index a0d8e3fa3..a73d0a9af 100644 --- a/libtorrent/src/http_connection.cpp +++ b/libtorrent/src/http_connection.cpp @@ -284,7 +284,17 @@ void http_connection::on_read(asio::error_code const& e { libtorrent::buffer::const_interval rcv_buf(&m_recvbuffer[0] , &m_recvbuffer[0] + m_read_pos); - m_parser.incoming(rcv_buf); + try + { + m_parser.incoming(rcv_buf); + } + catch (std::exception& e) + { + m_timer.cancel(); + m_handler(asio::error::fault, m_parser, 0, 0); + m_handler.clear(); + return; + } if (!m_bottled && m_parser.header_finished()) { if (m_read_pos > m_parser.body_start()) diff --git a/libtorrent/src/http_tracker_connection.cpp b/libtorrent/src/http_tracker_connection.cpp index 86d21e494..b9581e862 100755 --- a/libtorrent/src/http_tracker_connection.cpp +++ b/libtorrent/src/http_tracker_connection.cpp @@ -217,7 +217,11 @@ namespace libtorrent char dummy; std::string bytes; size_type range_start, range_end; - range_str >> bytes >> range_start >> dummy >> range_end; + // apparently some web servers do not send the "bytes" + // in their content-range + if (value.find(' ') != std::string::npos) + range_str >> bytes; + range_str >> range_start >> dummy >> range_end; if (!range_str || range_end < range_start) { throw std::runtime_error("invalid content-range in HTTP response: " + range_str.str()); diff --git a/libtorrent/src/kademlia/dht_tracker.cpp b/libtorrent/src/kademlia/dht_tracker.cpp index 3f47eb070..1a074bc20 100644 --- a/libtorrent/src/kademlia/dht_tracker.cpp +++ b/libtorrent/src/kademlia/dht_tracker.cpp @@ -405,6 +405,54 @@ namespace libtorrent { namespace dht if (error) return; + node_ban_entry* match = 0; + node_ban_entry* min = m_ban_nodes; + ptime now = time_now(); + for (node_ban_entry* i = m_ban_nodes; i < m_ban_nodes + num_ban_nodes; ++i) + { + if (i->src == m_remote_endpoint[current_buffer]) + { + match = i; + break; + } + if (i->count < min->count) min = i; + } + + if (match) + { + ++match->count; + if (match->count >= 20) + { + if (now < match->limit) + { +#ifdef TORRENT_DHT_VERBOSE_LOGGING + if (match->count == 20) + { + TORRENT_LOG(dht_tracker) << time_now_string() << " BANNING PEER [ ip: " + << m_remote_endpoint[current_buffer] << " | " + "time: " << total_seconds((now - match->limit) + seconds(5)) + << " | count: " << match->count << " ]"; + } +#endif + // we've received 20 messages in less than 5 seconds from + // this node. Ignore it until it's silent for 5 minutes + match->limit = now + minutes(5); + return; + } + + // we got 50 messages from this peer, but it was in + // more than 5 seconds. Reset the counter and the timer + match->count = 0; + match->limit = now + seconds(5); + } + } + else + { + min->count = 1; + min->limit = now + seconds(5); + min->src = m_remote_endpoint[current_buffer]; + } + #ifdef TORRENT_DHT_VERBOSE_LOGGING ++m_total_message_input; m_total_in_bytes += bytes_transferred; diff --git a/libtorrent/src/kademlia/rpc_manager.cpp b/libtorrent/src/kademlia/rpc_manager.cpp index 5ae448501..e4019bab8 100644 --- a/libtorrent/src/kademlia/rpc_manager.cpp +++ b/libtorrent/src/kademlia/rpc_manager.cpp @@ -213,11 +213,11 @@ bool rpc_manager::incoming(msg const& m) return false; } - if (m.addr != o->target_addr) + if (m.addr.address() != o->target_addr.address()) { #ifdef TORRENT_DHT_VERBOSE_LOGGING TORRENT_LOG(rpc) << "Reply with incorrect address and valid transaction id: " - << tid << " from " << m.addr; + << tid << " from " << m.addr << " expected: " << o->target_addr; #endif return false; } diff --git a/libtorrent/src/session.cpp b/libtorrent/src/session.cpp index 8efad6b0d..331ffa377 100755 --- a/libtorrent/src/session.cpp +++ b/libtorrent/src/session.cpp @@ -422,7 +422,7 @@ namespace libtorrent return m_impl->pop_alert(); } - std::auto_ptr session::wait_for_alert(time_duration max_wait) + alert const* session::wait_for_alert(time_duration max_wait) { return m_impl->wait_for_alert(max_wait); } diff --git a/libtorrent/src/session_impl.cpp b/libtorrent/src/session_impl.cpp index fdaacfabc..c1969d523 100755 --- a/libtorrent/src/session_impl.cpp +++ b/libtorrent/src/session_impl.cpp @@ -1836,7 +1836,7 @@ namespace detail t.abort(); if ((!t.is_paused() || t.should_request()) - && !t.torrent_file().trackers().empty()) + && !t.trackers().empty()) { tracker_request req = t.generate_tracker_request(); TORRENT_ASSERT(req.event == tracker_request::stopped); @@ -2272,7 +2272,7 @@ namespace detail return std::auto_ptr(0); } - std::auto_ptr session_impl::wait_for_alert(time_duration max_wait) + alert const* session_impl::wait_for_alert(time_duration max_wait) { return m_alerts.wait_for_alert(max_wait); } diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index d28c97d47..557289d60 100755 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -735,8 +735,10 @@ namespace libtorrent return make_tuple(m_torrent_file->total_size() , m_torrent_file->total_size()); + TORRENT_ASSERT(m_num_pieces >= m_picker->num_have_filtered()); size_type wanted_done = size_type(m_num_pieces - m_picker->num_have_filtered()) * piece_size; + TORRENT_ASSERT(wanted_done >= 0); size_type total_done = size_type(m_num_pieces) * piece_size; @@ -762,6 +764,7 @@ namespace libtorrent TORRENT_ASSERT(total_done <= m_torrent_file->total_size()); TORRENT_ASSERT(wanted_done <= m_torrent_file->total_size()); + TORRENT_ASSERT(total_done >= wanted_done); const std::vector& dl_queue = m_picker->get_download_queue(); @@ -2760,6 +2763,8 @@ namespace libtorrent #endif disconnect_all(); + if (!m_paused) + m_just_paused = true; m_paused = true; // tell the tracker that we stopped m_event = tracker_request::stopped; @@ -3033,6 +3038,7 @@ namespace libtorrent st.num_incomplete = m_incomplete; st.paused = m_paused; boost::tie(st.total_done, st.total_wanted_done) = bytes_done(); + TORRENT_ASSERT(st.total_done >= st.total_wanted_done); // payload transfer st.total_payload_download = m_stat.total_payload_download();