diff --git a/libtorrent/include/libtorrent/upnp.hpp b/libtorrent/include/libtorrent/upnp.hpp index 54e832c8a..5913e70d0 100644 --- a/libtorrent/include/libtorrent/upnp.hpp +++ b/libtorrent/include/libtorrent/upnp.hpp @@ -200,6 +200,9 @@ private: std::vector mapping; + // this is the hostname, port and path + // component of the url or the control_url + // if it has been found std::string hostname; int port; std::string path; diff --git a/libtorrent/src/broadcast_socket.cpp b/libtorrent/src/broadcast_socket.cpp index deefe23be..43654a11a 100644 --- a/libtorrent/src/broadcast_socket.cpp +++ b/libtorrent/src/broadcast_socket.cpp @@ -169,15 +169,13 @@ namespace libtorrent for (std::vector::const_iterator i = interfaces.begin() , end(interfaces.end()); i != end; ++i) { - // only broadcast to IPv4 addresses that are not local - if (is_local(i->interface_address)) continue; // only multicast on compatible networks if (i->interface_address.is_v4() != multicast_endpoint.address().is_v4()) continue; // ignore any loopback interface if (is_loopback(i->interface_address)) continue; #ifndef NDEBUG -// std::cerr << "broadcast socket [ if: " << i->to_v4().to_string() +// std::cerr << "broadcast socket [ if: " << i->interface_address.to_v4().to_string() // << " group: " << multicast_endpoint.address() << " ]" << std::endl; #endif open_unicast_socket(ios, i->interface_address); diff --git a/libtorrent/src/peer_connection.cpp b/libtorrent/src/peer_connection.cpp index 6efe61d94..455f55ece 100755 --- a/libtorrent/src/peer_connection.cpp +++ b/libtorrent/src/peer_connection.cpp @@ -294,6 +294,14 @@ namespace libtorrent if (rhs.m_peer_info) c2 = rhs.m_peer_info->total_upload(); else c2 = rhs.m_statistics.total_payload_upload(); + // in order to not switch back and forth too often, + // unchoked peers must be at least one piece ahead + // of a choked peer to be sorted at a lower unchoke-priority + boost::shared_ptr t = m_torrent.lock(); + TORRENT_ASSERT(t); + if (!is_choked()) c1 -= t->torrent_file().piece_length(); + if (!rhs.is_choked()) c2 -= t->torrent_file().piece_length(); + return c1 < c2; } @@ -778,8 +786,6 @@ namespace libtorrent // and if it can correspond to a request generated by libtorrent. bool peer_connection::verify_piece(const peer_request& p) const { - INVARIANT_CHECK; - boost::shared_ptr t = m_torrent.lock(); TORRENT_ASSERT(t); @@ -1616,7 +1622,7 @@ namespace libtorrent #ifndef NDEBUG check_postcondition post_checker_(t); -#if !defined TORRENT_DISABLE_INVARIANT_CHECKS +#if !defined TORRENT_DISABLE_INVARIANT_CHECKS && defined TORRENT_EXPENSIVE_INVARIANT_CHECKS t->check_invariant(); #endif #endif @@ -1791,7 +1797,8 @@ namespace libtorrent TORRENT_ASSERT(picker.num_peers(block_finished) == 0); -#if !defined NDEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS +#if !defined NDEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS \ + && defined TORRENT_EXPENSIVE_INVARIANT_CHECKS t->check_invariant(); #endif request_a_block(*t, *this); @@ -3064,7 +3071,9 @@ namespace libtorrent void peer_connection::fill_send_buffer() { +#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS INVARIANT_CHECK; +#endif boost::shared_ptr t = m_torrent.lock(); if (!t) return; @@ -3997,7 +4006,9 @@ namespace libtorrent void peer_connection::keep_alive() { +#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS INVARIANT_CHECK; +#endif time_duration d; d = time_now() - m_last_sent; diff --git a/libtorrent/src/piece_picker.cpp b/libtorrent/src/piece_picker.cpp index c8b5d8d99..c1941a6ff 100755 --- a/libtorrent/src/piece_picker.cpp +++ b/libtorrent/src/piece_picker.cpp @@ -122,7 +122,9 @@ namespace libtorrent void piece_picker::piece_info(int index, piece_picker::downloading_piece& st) const { +#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS TORRENT_PIECE_PICKER_INVARIANT_CHECK; +#endif TORRENT_ASSERT(index >= 0); TORRENT_ASSERT(index < int(m_piece_map.size())); @@ -1312,7 +1314,9 @@ namespace libtorrent // only one of rarest_first and sequential can be set. TORRENT_ASSERT(bool(options & rarest_first) + bool(options & sequential) <= 1); +#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS TORRENT_PIECE_PICKER_INVARIANT_CHECK; +#endif TORRENT_ASSERT(num_blocks > 0); TORRENT_ASSERT(pieces.size() == m_piece_map.size()); @@ -2173,7 +2177,9 @@ namespace libtorrent // a peer disconnects. The piece might be in any state void piece_picker::abort_download(piece_block block) { +#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS TORRENT_PIECE_PICKER_INVARIANT_CHECK; +#endif TORRENT_ASSERT(block.piece_index >= 0); TORRENT_ASSERT(block.block_index >= 0); diff --git a/libtorrent/src/session_impl.cpp b/libtorrent/src/session_impl.cpp index eab1b0638..2bb28478b 100755 --- a/libtorrent/src/session_impl.cpp +++ b/libtorrent/src/session_impl.cpp @@ -1353,19 +1353,23 @@ namespace aux { > bind(&torrent::seed_rank, _2, boost::ref(m_settings))); } + int total_running = 0; for (std::vector::iterator i = downloaders.begin() , end(downloaders.end()); i != end; ++i) { torrent* t = *i; - if (!t->is_paused() && !is_active(t, settings()) && hard_limit > 0) + if (!t->is_paused() && !is_active(t, settings()) + && hard_limit > 0 && total_running < m_max_uploads) { --hard_limit; + ++total_running; continue; } if (num_downloaders > 0 && hard_limit > 0) { --hard_limit; + ++total_running; if (t->state() != torrent_status::queued_for_checking && t->state() != torrent_status::checking_files) { @@ -1383,9 +1387,11 @@ namespace aux { , end(seeds.end()); i != end; ++i) { torrent* t = *i; - if (!t->is_paused() && !is_active(t, settings()) && hard_limit > 0) + if (!t->is_paused() && !is_active(t, settings()) + && hard_limit > 0 && total_running < m_max_uploads) { --hard_limit; + ++total_running; continue; } @@ -1393,6 +1399,7 @@ namespace aux { { --hard_limit; --num_seeds; + ++total_running; if (t->is_paused()) t->resume(); } else @@ -1410,6 +1417,7 @@ namespace aux { , end(m_connections.end()); i != end; ++i) { peer_connection* p = i->get(); + TORRENT_ASSERT(p); torrent* t = p->associated_torrent().lock().get(); if (!p->peer_info_struct() || t == 0 @@ -1455,7 +1463,8 @@ namespace aux { // limit if (m_stat.upload_rate() < upload_limit * 0.9f && m_allowed_upload_slots <= m_num_unchoked + 1 - && congested_torrents < uncongested_torrents) + && congested_torrents < uncongested_torrents + && m_upload_channel.queue_size() < 2) { ++m_allowed_upload_slots; } @@ -1494,6 +1503,8 @@ namespace aux { if (p->peer_info_struct()->optimistically_unchoked) { // force a new optimistic unchoke + // since this one just got promoted into the + // proper unchoke set m_optimistic_unchoke_time_scaler = 0; p->peer_info_struct()->optimistically_unchoked = false; } diff --git a/libtorrent/src/storage.cpp b/libtorrent/src/storage.cpp index 737d1aa17..c21f68fbb 100755 --- a/libtorrent/src/storage.cpp +++ b/libtorrent/src/storage.cpp @@ -523,7 +523,8 @@ namespace libtorrent // the directory exists. if (file_iter->size == 0) { - file(m_save_path / file_iter->path, file::out, ec); + boost::shared_ptr f = m_pool.open_file(this + , m_save_path / file_iter->path, file::in | file::out, ec); if (ec) { set_error(m_save_path / file_iter->path, ec); diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index f7ec7f5ef..c1a5ab8de 100755 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -2069,7 +2069,15 @@ namespace libtorrent } if (!p->is_choked()) + { --m_num_uploads; + m_ses.m_unchoke_time_scaler = 0; + } + + if (p->peer_info_struct() && p->peer_info_struct()->optimistically_unchoked) + { + m_ses.m_optimistic_unchoke_time_scaler = 0; + } m_policy.connection_closed(*p); p->set_peer_info(0); diff --git a/libtorrent/src/upnp.cpp b/libtorrent/src/upnp.cpp index d98e95284..baac6ca4f 100644 --- a/libtorrent/src/upnp.cpp +++ b/libtorrent/src/upnp.cpp @@ -141,7 +141,7 @@ void upnp::discover_device_impl() } ++m_retry_count; - m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count), ec); + m_broadcast_timer.expires_from_now(seconds(2 * m_retry_count), ec); m_broadcast_timer.async_wait(bind(&upnp::resend_request , self(), _1)); @@ -240,7 +240,7 @@ void upnp::resend_request(error_code const& e) mutex_t::scoped_lock l(m_mutex); - if (m_retry_count < 9 + if (m_retry_count < 12 && (m_devices.empty() || m_retry_count < 4)) { discover_device_impl(); @@ -251,7 +251,7 @@ void upnp::resend_request(error_code const& e) { #ifdef TORRENT_UPNP_LOGGING m_log << time_now_string() - << " *** Got no response in 9 retries. Giving up, " + << " *** Got no response in 12 retries. Giving up, " "disabling UPnP." << std::endl; #endif disable("no UPnP router found"); @@ -560,7 +560,7 @@ void upnp::post(upnp::rootdevice const& d, std::string const& soap std::stringstream header; - header << "POST " << d.control_url << " HTTP/1.1\r\n" + header << "POST " << d.path << " HTTP/1.0\r\n" "Host: " << d.hostname << ":" << d.port << "\r\n" "Content-Type: text/xml; charset=\"utf-8\"\r\n" "Content-Length: " << soap.size() << "\r\n" @@ -876,6 +876,22 @@ void upnp::on_upnp_xml(error_code const& e d.control_url = s.control_url; + std::string protocol; + std::string auth; + char const* error; + boost::tie(protocol, auth, d.hostname, d.port, d.path, error) + = parse_url_components(d.control_url); + + if (error) + { +#ifdef TORRENT_UPNP_LOGGING + m_log << time_now_string() + << " *** Failed to parse URL '" << d.control_url << "': " << error << std::endl; +#endif + d.disabled = true; + return; + } + if (num_mappings() > 0) update_map(d, 0); }