From cfe1bd241d0009c01597ddda5d59f99dfe105141 Mon Sep 17 00:00:00 2001 From: Marcos Pinto Date: Sat, 1 Dec 2007 03:54:42 +0000 Subject: [PATCH] fix duplicant_torrent and libtorrent bugfixes --- libtorrent/include/libtorrent/alert.hpp | 4 + .../include/libtorrent/aux_/session_impl.hpp | 2 + libtorrent/include/libtorrent/session.hpp | 3 + .../include/libtorrent/session_settings.hpp | 4 + libtorrent/include/libtorrent/time.hpp | 1 + libtorrent/include/libtorrent/torrent.hpp | 11 +- .../include/libtorrent/torrent_info.hpp | 10 +- libtorrent/src/Makefile.in | 32 +- libtorrent/src/alert.cpp | 26 + libtorrent/src/kademlia/dht_tracker.cpp | 3 + libtorrent/src/kademlia/rpc_manager.cpp | 16 +- libtorrent/src/session.cpp | 5 + libtorrent/src/session_impl.cpp | 10 + libtorrent/src/socks4_stream.cpp | 23 +- libtorrent/src/socks5_stream.cpp | 53 +- libtorrent/src/storage.cpp | 18 +- libtorrent/src/torrent.cpp | 159 ++++- libtorrent/src/torrent_handle.cpp | 637 +++++------------- libtorrent/src/torrent_info.cpp | 35 +- libtorrent/src/web_peer_connection.cpp | 44 +- src/deluge_core.cpp | 44 +- 21 files changed, 535 insertions(+), 605 deletions(-) diff --git a/libtorrent/include/libtorrent/alert.hpp b/libtorrent/include/libtorrent/alert.hpp index 954e39ef5..ab8065f1f 100755 --- a/libtorrent/include/libtorrent/alert.hpp +++ b/libtorrent/include/libtorrent/alert.hpp @@ -43,6 +43,7 @@ POSSIBILITY OF SUCH DAMAGE. #endif #include +#include #include #include @@ -99,10 +100,13 @@ namespace libtorrent { void set_severity(alert::severity_t severity); bool should_post(alert::severity_t severity) const; + alert const* wait_for_alert(time_duration max_wait); + private: std::queue m_alerts; alert::severity_t m_severity; mutable boost::mutex m_mutex; + boost::condition m_condition; }; struct TORRENT_EXPORT unhandled_alert : std::exception diff --git a/libtorrent/include/libtorrent/aux_/session_impl.hpp b/libtorrent/include/libtorrent/aux_/session_impl.hpp index 95089b649..cf627c70b 100644 --- a/libtorrent/include/libtorrent/aux_/session_impl.hpp +++ b/libtorrent/include/libtorrent/aux_/session_impl.hpp @@ -280,6 +280,8 @@ namespace libtorrent void set_severity_level(alert::severity_t s); std::auto_ptr pop_alert(); + 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/session.hpp b/libtorrent/include/libtorrent/session.hpp index 1d29e03b3..d2ab6ab2e 100755 --- a/libtorrent/include/libtorrent/session.hpp +++ b/libtorrent/include/libtorrent/session.hpp @@ -60,6 +60,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/session_status.hpp" #include "libtorrent/version.hpp" #include "libtorrent/fingerprint.hpp" +#include "libtorrent/time.hpp" #include "libtorrent/storage.hpp" @@ -264,6 +265,8 @@ namespace libtorrent std::auto_ptr pop_alert(); void set_severity_level(alert::severity_t s); + alert const* wait_for_alert(time_duration max_wait); + connection_queue& get_connection_queue(); // starts/stops UPnP, NATPMP or LSD port mappers diff --git a/libtorrent/include/libtorrent/session_settings.hpp b/libtorrent/include/libtorrent/session_settings.hpp index 2cf71bb1f..7cc7d26da 100644 --- a/libtorrent/include/libtorrent/session_settings.hpp +++ b/libtorrent/include/libtorrent/session_settings.hpp @@ -95,6 +95,7 @@ namespace libtorrent , peer_timeout(120) , urlseed_timeout(20) , urlseed_pipeline_size(5) + , urlseed_wait_retry(30) , file_pool_size(40) , allow_multiple_connections_per_ip(false) , max_failcount(3) @@ -185,6 +186,9 @@ namespace libtorrent // controls the pipelining size of url-seeds int urlseed_pipeline_size; + + // time to wait until a new retry takes place + int urlseed_wait_retry; // sets the upper limit on the total number of files this // session will keep open. The reason why files are diff --git a/libtorrent/include/libtorrent/time.hpp b/libtorrent/include/libtorrent/time.hpp index 1aae81d3a..4ab7a3819 100644 --- a/libtorrent/include/libtorrent/time.hpp +++ b/libtorrent/include/libtorrent/time.hpp @@ -98,6 +98,7 @@ namespace libtorrent time_duration() {} 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; } boost::int64_t diff; }; diff --git a/libtorrent/include/libtorrent/torrent.hpp b/libtorrent/include/libtorrent/torrent.hpp index 7aa779081..0f508e93f 100755 --- a/libtorrent/include/libtorrent/torrent.hpp +++ b/libtorrent/include/libtorrent/torrent.hpp @@ -206,7 +206,7 @@ namespace libtorrent tcp::endpoint const& get_interface() const { return m_net_interface; } void connect_to_url_seed(std::string const& url); - bool connect_to_peer(policy::peer* peerinfo) throw(); + bool connect_to_peer(policy::peer* peerinfo); void set_ratio(float ratio) { TORRENT_ASSERT(ratio >= 0.0f); m_ratio = ratio; } @@ -254,6 +254,8 @@ namespace libtorrent void remove_url_seed(std::string const& url) { m_web_seeds.erase(url); } + void retry_url_seed(std::string const& url); + std::set url_seeds() const { return m_web_seeds; } @@ -293,6 +295,9 @@ namespace libtorrent void resolve_peer_country(boost::intrusive_ptr const& p) const; + void get_peer_info(std::vector& v); + void get_download_queue(std::vector& queue); + // -------------------------------------------- // TRACKER MANAGEMENT @@ -623,6 +628,10 @@ namespace libtorrent // The list of web seeds in this torrent. Seeds // with fatal errors are removed from the set std::set m_web_seeds; + + // a list of web seeds that have failed and are + // waiting to be retried + std::map m_web_seeds_next_retry; // urls of the web seeds that we are currently // resolving the address for diff --git a/libtorrent/include/libtorrent/torrent_info.hpp b/libtorrent/include/libtorrent/torrent_info.hpp index 16eebf234..a064936ff 100755 --- a/libtorrent/include/libtorrent/torrent_info.hpp +++ b/libtorrent/include/libtorrent/torrent_info.hpp @@ -69,9 +69,15 @@ namespace libtorrent struct TORRENT_EXPORT file_entry { + file_entry(): offset(0), size(0), file_base(0) {} + fs::path path; size_type offset; // the offset of this file inside the torrent size_type size; // the size of this file + // the offset in the file where the storage starts. + // This is always 0 unless parts of the torrent is + // compressed into a single file, such as a so-called part file. + size_type file_base; // if the path was incorrectly encoded, this is // the original corrupt encoded string. It is // preserved in order to be able to reproduce @@ -117,7 +123,7 @@ namespace libtorrent void add_file(fs::path file, size_type size); void add_url_seed(std::string const& url); - bool remap_files(std::vector > const& map); + bool remap_files(std::vector const& map); std::vector map_block(int piece, size_type offset , int size, bool storage = false) const; @@ -271,7 +277,7 @@ namespace libtorrent // this vector is typically empty. If it is not // empty, it means the user has re-mapped the - // files in this torrent to diffefrent names + // files in this torrent to different names // on disk. This is only used when reading and // writing the disk. std::vector m_remapped_files; diff --git a/libtorrent/src/Makefile.in b/libtorrent/src/Makefile.in index 0d08f513d..9721fd59e 100644 --- a/libtorrent/src/Makefile.in +++ b/libtorrent/src/Makefile.in @@ -64,18 +64,18 @@ am__libtorrent_la_SOURCES_DIST = entry.cpp escape_string.cpp \ peer_connection.cpp bt_peer_connection.cpp \ web_peer_connection.cpp natpmp.cpp piece_picker.cpp policy.cpp \ session.cpp session_impl.cpp sha1.cpp stat.cpp storage.cpp \ - torrent.cpp torrent_handle.cpp pe_crypto.cpp torrent_info.cpp \ - tracker_manager.cpp http_connection.cpp \ - http_tracker_connection.cpp udp_tracker_connection.cpp \ - alert.cpp identify_client.cpp ip_filter.cpp file.cpp \ - metadata_transfer.cpp logger.cpp file_pool.cpp ut_pex.cpp \ - lsd.cpp upnp.cpp instantiate_connection.cpp socks5_stream.cpp \ - socks4_stream.cpp http_stream.cpp connection_queue.cpp \ - disk_io_thread.cpp kademlia/closest_nodes.cpp \ - kademlia/dht_tracker.cpp kademlia/find_data.cpp \ - kademlia/node.cpp kademlia/node_id.cpp kademlia/refresh.cpp \ - kademlia/routing_table.cpp kademlia/rpc_manager.cpp \ - kademlia/traversal_algorithm.cpp + mapped_storage.cpp torrent.cpp torrent_handle.cpp \ + pe_crypto.cpp torrent_info.cpp tracker_manager.cpp \ + http_connection.cpp http_tracker_connection.cpp \ + udp_tracker_connection.cpp alert.cpp identify_client.cpp \ + ip_filter.cpp file.cpp metadata_transfer.cpp logger.cpp \ + file_pool.cpp ut_pex.cpp lsd.cpp upnp.cpp \ + instantiate_connection.cpp socks5_stream.cpp socks4_stream.cpp \ + http_stream.cpp connection_queue.cpp disk_io_thread.cpp \ + kademlia/closest_nodes.cpp kademlia/dht_tracker.cpp \ + kademlia/find_data.cpp kademlia/node.cpp kademlia/node_id.cpp \ + kademlia/refresh.cpp kademlia/routing_table.cpp \ + kademlia/rpc_manager.cpp kademlia/traversal_algorithm.cpp @USE_DHT_TRUE@am__objects_1 = closest_nodes.lo dht_tracker.lo \ @USE_DHT_TRUE@ find_data.lo node.lo node_id.lo refresh.lo \ @USE_DHT_TRUE@ routing_table.lo rpc_manager.lo \ @@ -84,8 +84,9 @@ am_libtorrent_la_OBJECTS = entry.lo escape_string.lo assert.lo \ enum_net.lo broadcast_socket.lo peer_connection.lo \ bt_peer_connection.lo web_peer_connection.lo natpmp.lo \ piece_picker.lo policy.lo session.lo session_impl.lo sha1.lo \ - stat.lo storage.lo torrent.lo torrent_handle.lo pe_crypto.lo \ - torrent_info.lo tracker_manager.lo http_connection.lo \ + stat.lo storage.lo mapped_storage.lo torrent.lo \ + torrent_handle.lo pe_crypto.lo torrent_info.lo \ + tracker_manager.lo http_connection.lo \ http_tracker_connection.lo udp_tracker_connection.lo alert.lo \ identify_client.lo ip_filter.lo file.lo metadata_transfer.lo \ logger.lo file_pool.lo ut_pex.lo lsd.lo upnp.lo \ @@ -251,7 +252,7 @@ libtorrent_la_SOURCES = entry.cpp escape_string.cpp \ assert.cpp enum_net.cpp broadcast_socket.cpp \ peer_connection.cpp bt_peer_connection.cpp web_peer_connection.cpp \ natpmp.cpp piece_picker.cpp policy.cpp session.cpp session_impl.cpp sha1.cpp \ -stat.cpp storage.cpp torrent.cpp torrent_handle.cpp pe_crypto.cpp \ +stat.cpp storage.cpp mapped_storage.cpp torrent.cpp torrent_handle.cpp pe_crypto.cpp \ torrent_info.cpp tracker_manager.cpp http_connection.cpp \ http_tracker_connection.cpp udp_tracker_connection.cpp \ alert.cpp identify_client.cpp ip_filter.cpp file.cpp metadata_transfer.cpp \ @@ -422,6 +423,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ip_filter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logger.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lsd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mapped_storage.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/metadata_transfer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/natpmp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node.Plo@am__quote@ diff --git a/libtorrent/src/alert.cpp b/libtorrent/src/alert.cpp index 1401a5e4a..cb89147da 100755 --- a/libtorrent/src/alert.cpp +++ b/libtorrent/src/alert.cpp @@ -33,6 +33,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/pch.hpp" #include "libtorrent/alert.hpp" +#include namespace libtorrent { @@ -77,6 +78,30 @@ namespace libtorrent { } } + alert const* alert_manager::wait_for_alert(time_duration max_wait) + { + boost::mutex::scoped_lock lock(m_mutex); + + if (!m_alerts.empty()) return m_alerts.front(); + + int secs = total_seconds(max_wait); + max_wait -= seconds(secs); + boost::xtime xt; + boost::xtime_get(&xt, boost::TIME_UTC); + xt.sec += secs; + boost::int64_t nsec = xt.nsec + total_microseconds(max_wait) * 1000; + if (nsec > 1000000000) + { + nsec -= 1000000000; + xt.sec += 1; + } + xt.nsec = nsec; + if (!m_condition.timed_wait(lock, xt)) return 0; + TORRENT_ASSERT(!m_alerts.empty()); + if (m_alerts.empty()) return 0; + return m_alerts.front(); + } + void alert_manager::post_alert(const alert& alert_) { boost::mutex::scoped_lock lock(m_mutex); @@ -90,6 +115,7 @@ namespace libtorrent { delete result; } m_alerts.push(alert_.clone().release()); + m_condition.notify_all(); } std::auto_ptr alert_manager::get() diff --git a/libtorrent/src/kademlia/dht_tracker.cpp b/libtorrent/src/kademlia/dht_tracker.cpp index f32db06d4..3f47eb070 100644 --- a/libtorrent/src/kademlia/dht_tracker.cpp +++ b/libtorrent/src/kademlia/dht_tracker.cpp @@ -273,6 +273,9 @@ namespace libtorrent { namespace dht udp::endpoint ep(listen_interface, listen_port); m_socket.open(ep.protocol()); m_socket.bind(ep); + m_socket.async_receive_from(asio::buffer(&m_in_buf[m_buffer][0] + , m_in_buf[m_buffer].size()), m_remote_endpoint[m_buffer] + , m_strand.wrap(bind(&dht_tracker::on_receive, self(), _1, _2))); } void dht_tracker::tick(asio::error_code const& e) diff --git a/libtorrent/src/kademlia/rpc_manager.cpp b/libtorrent/src/kademlia/rpc_manager.cpp index 086b8fc44..5ae448501 100644 --- a/libtorrent/src/kademlia/rpc_manager.cpp +++ b/libtorrent/src/kademlia/rpc_manager.cpp @@ -226,6 +226,10 @@ bool rpc_manager::incoming(msg const& m) std::ofstream reply_stats("libtorrent_logs/round_trip_ms.log", std::ios::app); reply_stats << m.addr << "\t" << total_milliseconds(time_now() - o->sent) << std::endl; +#endif +#ifdef TORRENT_DHT_VERBOSE_LOGGING + TORRENT_LOG(rpc) << "Reply with transaction id: " + << tid << " from " << m.addr; #endif o->reply(m); m_transactions[tid] = 0; @@ -284,6 +288,10 @@ time_duration rpc_manager::tick() try { m_transactions[m_oldest_transaction_id] = 0; +#ifdef TORRENT_DHT_VERBOSE_LOGGING + TORRENT_LOG(rpc) << "Timing out transaction id: " + << m_oldest_transaction_id << " from " << o->target_addr; +#endif timeouts.push_back(o); } catch (std::exception) {} } @@ -309,7 +317,13 @@ unsigned int rpc_manager::new_transaction_id(observer_ptr o) // moving the observer into the set of aborted transactions // it will prevent it from spawning new requests right now, // since that would break the invariant - m_aborted_transactions.push_back(m_transactions[m_next_transaction_id]); + observer_ptr o = m_transactions[m_next_transaction_id]; + m_aborted_transactions.push_back(o); +#ifdef TORRENT_DHT_VERBOSE_LOGGING + TORRENT_LOG(rpc) << "[new_transaction_id] Aborting message with transaction id: " + << m_next_transaction_id << " sent to " << o->target_addr + << " " << total_seconds(time_now() - o->sent) << " seconds ago"; +#endif m_transactions[m_next_transaction_id] = 0; TORRENT_ASSERT(m_oldest_transaction_id == m_next_transaction_id); } diff --git a/libtorrent/src/session.cpp b/libtorrent/src/session.cpp index 0b8aecff7..331ffa377 100755 --- a/libtorrent/src/session.cpp +++ b/libtorrent/src/session.cpp @@ -422,6 +422,11 @@ namespace libtorrent return m_impl->pop_alert(); } + alert const* session::wait_for_alert(time_duration max_wait) + { + return m_impl->wait_for_alert(max_wait); + } + void session::set_severity_level(alert::severity_t s) { m_impl->set_severity_level(s); diff --git a/libtorrent/src/session_impl.cpp b/libtorrent/src/session_impl.cpp index 69f2c1bc1..833d49777 100755 --- a/libtorrent/src/session_impl.cpp +++ b/libtorrent/src/session_impl.cpp @@ -2251,6 +2251,11 @@ namespace detail return m_alerts.get(); return std::auto_ptr(0); } + + alert const* session_impl::wait_for_alert(time_duration max_wait) + { + return m_alerts.wait_for_alert(max_wait); + } void session_impl::set_severity_level(alert::severity_t s) { @@ -2414,6 +2419,11 @@ namespace detail { TORRENT_ASSERT(false); } + for (std::map >::const_iterator j + = m_torrents.begin(); j != m_torrents.end(); ++j) + { + TORRENT_ASSERT(boost::get_pointer(j->second)); + } } #endif diff --git a/libtorrent/src/socks4_stream.cpp b/libtorrent/src/socks4_stream.cpp index 3a31b2375..c96dde85b 100644 --- a/libtorrent/src/socks4_stream.cpp +++ b/libtorrent/src/socks4_stream.cpp @@ -43,7 +43,8 @@ namespace libtorrent if (e) { (*h)(e); - close(); + asio::error_code ec; + close(ec); return; } @@ -54,8 +55,8 @@ namespace libtorrent if (i == tcp::resolver::iterator()) { asio::error_code ec = asio::error::operation_not_supported; - (*h)(e); - close(); + (*h)(ec); + close(ec); return; } @@ -68,7 +69,8 @@ namespace libtorrent if (e) { (*h)(e); - close(); + asio::error_code ec; + close(ec); return; } @@ -93,7 +95,8 @@ namespace libtorrent if (e) { (*h)(e); - close(); + asio::error_code ec; + close(ec); return; } @@ -107,7 +110,8 @@ namespace libtorrent if (e) { (*h)(e); - close(); + asio::error_code ec; + close(ec); return; } @@ -119,8 +123,9 @@ namespace libtorrent if (reply_version != 0) { - (*h)(asio::error::operation_not_supported); - close(); + asio::error_code ec = asio::error::operation_not_supported; + (*h)(ec); + close(ec); return; } @@ -140,7 +145,7 @@ namespace libtorrent case 93: ec = asio::error::no_permission; break; } (*h)(ec); - close(); + close(ec); } } diff --git a/libtorrent/src/socks5_stream.cpp b/libtorrent/src/socks5_stream.cpp index a40cd33d0..f0c41c02b 100644 --- a/libtorrent/src/socks5_stream.cpp +++ b/libtorrent/src/socks5_stream.cpp @@ -44,7 +44,8 @@ namespace libtorrent if (e || i == tcp::resolver::iterator()) { (*h)(e); - close(); + asio::error_code ec; + close(ec); return; } @@ -57,7 +58,8 @@ namespace libtorrent if (e) { (*h)(e); - close(); + asio::error_code ec; + close(ec); return; } @@ -86,7 +88,8 @@ namespace libtorrent if (e) { (*h)(e); - close(); + asio::error_code ec; + close(ec); return; } @@ -100,7 +103,8 @@ namespace libtorrent if (e) { (*h)(e); - close(); + asio::error_code ec; + close(ec); return; } @@ -113,7 +117,8 @@ namespace libtorrent if (version < 5) { (*h)(asio::error::operation_not_supported); - close(); + asio::error_code ec; + close(ec); return; } @@ -126,7 +131,8 @@ namespace libtorrent if (m_user.empty()) { (*h)(asio::error::operation_not_supported); - close(); + asio::error_code ec; + close(ec); return; } @@ -144,7 +150,8 @@ namespace libtorrent else { (*h)(asio::error::operation_not_supported); - close(); + asio::error_code ec; + close(ec); return; } } @@ -155,7 +162,8 @@ namespace libtorrent if (e) { (*h)(e); - close(); + asio::error_code ec; + close(ec); return; } @@ -170,7 +178,8 @@ namespace libtorrent if (e) { (*h)(e); - close(); + asio::error_code ec; + close(ec); return; } @@ -183,19 +192,21 @@ namespace libtorrent if (version != 1) { (*h)(asio::error::operation_not_supported); - close(); + asio::error_code ec; + close(ec); return; } if (status != 0) { (*h)(asio::error::operation_not_supported); - close(); + asio::error_code ec; + close(ec); return; } std::vector().swap(m_buffer); - (*h)(e); + socks_connect(h); } void socks5_stream::socks_connect(boost::shared_ptr h) @@ -222,7 +233,8 @@ namespace libtorrent if (e) { (*h)(e); - close(); + asio::error_code ec; + close(ec); return; } @@ -236,7 +248,8 @@ namespace libtorrent if (e) { (*h)(e); - close(); + asio::error_code ec; + close(ec); return; } @@ -248,7 +261,8 @@ namespace libtorrent if (version < 5) { (*h)(asio::error::operation_not_supported); - close(); + asio::error_code ec; + close(ec); return; } int response = read_uint8(p); @@ -267,7 +281,8 @@ namespace libtorrent case 8: e = asio::error::address_family_not_supported; break; } (*h)(e); - close(); + asio::error_code ec; + close(ec); return; } p += 1; // reserved @@ -291,7 +306,8 @@ namespace libtorrent else { (*h)(asio::error::operation_not_supported); - close(); + asio::error_code ec; + close(ec); return; } m_buffer.resize(skip_bytes); @@ -305,7 +321,8 @@ namespace libtorrent if (e) { (*h)(e); - close(); + asio::error_code ec; + close(ec); return; } diff --git a/libtorrent/src/storage.cpp b/libtorrent/src/storage.cpp index cf0781e6a..07878e7ee 100755 --- a/libtorrent/src/storage.cpp +++ b/libtorrent/src/storage.cpp @@ -768,10 +768,10 @@ namespace libtorrent TORRENT_ASSERT(file_offset < file_iter->size); - TORRENT_ASSERT(slices[0].offset == file_offset); + TORRENT_ASSERT(slices[0].offset == file_offset + file_iter->file_base); - size_type new_pos = in->seek(file_offset); - if (new_pos != file_offset) + size_type new_pos = in->seek(file_offset + file_iter->file_base); + if (new_pos != file_offset + file_iter->file_base) { // the file was not big enough if (!fill_zero) @@ -782,7 +782,7 @@ namespace libtorrent #ifndef NDEBUG size_type in_tell = in->tell(); - TORRENT_ASSERT(in_tell == file_offset); + TORRENT_ASSERT(in_tell == file_offset + file_iter->file_base); #endif int left_to_read = size; @@ -846,7 +846,7 @@ namespace libtorrent file_offset = 0; in = m_files.open_file( this, path, file::in); - in->seek(0); + in->seek(file_iter->file_base); } } return result; @@ -892,11 +892,11 @@ namespace libtorrent this, p, file::out | file::in); TORRENT_ASSERT(file_offset < file_iter->size); - TORRENT_ASSERT(slices[0].offset == file_offset); + TORRENT_ASSERT(slices[0].offset == file_offset + file_iter->file_base); - size_type pos = out->seek(file_offset); + size_type pos = out->seek(file_offset + file_iter->file_base); - if (pos != file_offset) + if (pos != file_offset + file_iter->file_base) { std::stringstream s; s << "no storage for slot " << slot; @@ -962,7 +962,7 @@ namespace libtorrent out = m_files.open_file( this, p, file::out | file::in); - out->seek(0); + out->seek(file_iter->file_base); } } } diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index 33a73d1f3..d28c97d47 100755 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -287,6 +287,10 @@ namespace libtorrent #ifndef TORRENT_DISABLE_DHT bool torrent::should_announce_dht() const { + if (m_ses.m_listen_sockets.empty()) return false; + + if (!m_ses.m_dht) return false; + // don't announce private torrents if (m_torrent_file->is_valid() && m_torrent_file->priv()) return false; @@ -434,7 +438,8 @@ namespace libtorrent bind(&torrent::on_announce_disp, self, _1))); // announce with the local discovery service - m_ses.announce_lsd(m_torrent_file->info_hash()); + if (!m_paused) + m_ses.announce_lsd(m_torrent_file->info_hash()); } else { @@ -444,14 +449,12 @@ namespace libtorrent } #ifndef TORRENT_DISABLE_DHT + if (m_paused) return; if (!m_ses.m_dht) return; ptime now = time_now(); if (should_announce_dht() && now - m_last_dht_announce > minutes(14)) { m_last_dht_announce = now; - // TODO: There should be a way to abort an announce operation on the dht. - // when the torrent is destructed - if (m_ses.m_listen_sockets.empty()) return; m_ses.m_dht->announce(m_torrent_file->info_hash() , m_ses.m_listen_sockets.front().external_port , m_ses.m_strand.wrap(bind(&torrent::on_dht_announce_response_disp, self, _1))); @@ -701,7 +704,7 @@ namespace libtorrent const int last_piece = m_torrent_file->num_pieces() - 1; size_type total_done - = m_num_pieces * m_torrent_file->piece_length(); + = size_type(m_num_pieces) * m_torrent_file->piece_length(); // if we have the last piece, we have to correct // the amount we have, since the first calculation @@ -726,16 +729,17 @@ namespace libtorrent return tuple(0,0); const int last_piece = m_torrent_file->num_pieces() - 1; + const int piece_size = m_torrent_file->piece_length(); if (is_seed()) return make_tuple(m_torrent_file->total_size() , m_torrent_file->total_size()); - size_type wanted_done = (m_num_pieces - m_picker->num_have_filtered()) - * m_torrent_file->piece_length(); + size_type wanted_done = size_type(m_num_pieces - m_picker->num_have_filtered()) + * piece_size; size_type total_done - = m_num_pieces * m_torrent_file->piece_length(); + = size_type(m_num_pieces) * piece_size; TORRENT_ASSERT(m_num_pieces < m_torrent_file->num_pieces()); // if we have the last piece, we have to correct @@ -743,11 +747,17 @@ namespace libtorrent // assumed all pieces were of equal size if (m_have_pieces[last_piece]) { + TORRENT_ASSERT(total_done >= piece_size); int corr = m_torrent_file->piece_size(last_piece) - - m_torrent_file->piece_length(); + - piece_size; + TORRENT_ASSERT(corr <= 0); + TORRENT_ASSERT(corr > -piece_size); total_done += corr; if (m_picker->piece_priority(last_piece) != 0) + { + TORRENT_ASSERT(wanted_done >= piece_size); wanted_done += corr; + } } TORRENT_ASSERT(total_done <= m_torrent_file->total_size()); @@ -757,7 +767,7 @@ namespace libtorrent = m_picker->get_download_queue(); const int blocks_per_piece = static_cast( - m_torrent_file->piece_length() / m_block_size); + piece_size / m_block_size); for (std::vector::const_iterator i = dl_queue.begin(); i != dl_queue.end(); ++i) @@ -779,6 +789,7 @@ namespace libtorrent { TORRENT_ASSERT(m_picker->is_finished(piece_block(index, j)) == (i->info[j].state == piece_picker::block_info::state_finished)); corr += (i->info[j].state == piece_picker::block_info::state_finished) * m_block_size; + TORRENT_ASSERT(corr >= 0); TORRENT_ASSERT(index != last_piece || j < m_picker->blocks_in_last_piece() || i->info[j].state != piece_picker::block_info::state_finished); } @@ -1913,7 +1924,101 @@ namespace libtorrent } #endif - bool torrent::connect_to_peer(policy::peer* peerinfo) throw() + void torrent::get_peer_info(std::vector& v) + { + v.clear(); + for (peer_iterator i = begin(); + i != end(); ++i) + { + peer_connection* peer = *i; + + // incoming peers that haven't finished the handshake should + // not be included in this list + if (peer->associated_torrent().expired()) continue; + + v.push_back(peer_info()); + peer_info& p = v.back(); + + peer->get_peer_info(p); +#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES + if (resolving_countries()) + resolve_peer_country(intrusive_ptr(peer)); +#endif + } + } + + void torrent::get_download_queue(std::vector& queue) + { + queue.clear(); + if (!valid_metadata() || is_seed()) return; + piece_picker const& p = picker(); + std::vector const& q + = p.get_download_queue(); + + for (std::vector::const_iterator i + = q.begin(); i != q.end(); ++i) + { + partial_piece_info pi; + pi.piece_state = (partial_piece_info::state_t)i->state; + pi.blocks_in_piece = p.blocks_in_piece(i->index); + pi.finished = (int)i->finished; + pi.writing = (int)i->writing; + pi.requested = (int)i->requested; + int piece_size = torrent_file().piece_size(i->index); + for (int j = 0; j < pi.blocks_in_piece; ++j) + { + block_info& bi = pi.blocks[j]; + bi.state = i->info[j].state; + bi.block_size = j < pi.blocks_in_piece - 1 ? m_block_size + : piece_size - (j * m_block_size); + bool complete = bi.state == block_info::writing + || bi.state == block_info::finished; + if (i->info[j].peer == 0) + { + bi.peer = tcp::endpoint(); + bi.bytes_progress = complete ? bi.block_size : 0; + } + else + { + policy::peer* p = static_cast(i->info[j].peer); + if (p->connection) + { + bi.peer = p->connection->remote(); + if (bi.state == block_info::requested) + { + boost::optional pbp + = p->connection->downloading_piece_progress(); + if (pbp && pbp->piece_index == i->index && pbp->block_index == j) + { + bi.bytes_progress = pbp->bytes_downloaded; + TORRENT_ASSERT(bi.bytes_progress <= bi.block_size); + } + else + { + bi.bytes_progress = 0; + } + } + else + { + bi.bytes_progress = complete ? bi.block_size : 0; + } + } + else + { + bi.peer = p->ip; + bi.bytes_progress = complete ? bi.block_size : 0; + } + } + + pi.blocks[j].num_peers = i->info[j].num_peers; + } + pi.piece_index = i->index; + queue.push_back(pi); + } + + } + + bool torrent::connect_to_peer(policy::peer* peerinfo) { INVARIANT_CHECK; @@ -2249,16 +2354,18 @@ namespace libtorrent m_next_request = time_now() + seconds(delay); #ifndef TORRENT_DISABLE_DHT + if (m_abort) return; + // only start the announce if we want to announce with the dht - if (should_announce_dht()) + ptime now = time_now(); + if (should_announce_dht() && now - m_last_dht_announce > minutes(14)) { - if (m_abort) return; // force the DHT to reannounce - m_last_dht_announce = time_now() - minutes(15); + m_last_dht_announce = now; boost::weak_ptr self(shared_from_this()); - m_announce_timer.expires_from_now(seconds(1)); - m_announce_timer.async_wait(m_ses.m_strand.wrap( - bind(&torrent::on_announce_disp, self, _1))); + m_ses.m_dht->announce(m_torrent_file->info_hash() + , m_ses.m_listen_sockets.front().external_port + , m_ses.m_strand.wrap(bind(&torrent::on_dht_announce_response_disp, self, _1))); } #endif @@ -2747,6 +2854,18 @@ namespace libtorrent // ---- WEB SEEDS ---- + // re-insert urls that are to be retries into the m_web_seeds + typedef std::map::iterator iter_t; + for (iter_t i = m_web_seeds_next_retry.begin(); i != m_web_seeds_next_retry.end();) + { + iter_t erase_element = i++; + if (erase_element->second <= time_now()) + { + m_web_seeds.insert(erase_element->first); + m_web_seeds_next_retry.erase(erase_element); + } + } + // if we have everything we want we don't need to connect to any web-seed if (!is_finished() && !m_web_seeds.empty()) { @@ -2809,6 +2928,12 @@ namespace libtorrent } } + void torrent::retry_url_seed(std::string const& url) + { + m_web_seeds_next_retry[url] = time_now() + + seconds(m_ses.settings().urlseed_wait_retry); + } + bool torrent::try_connect_peer() { TORRENT_ASSERT(want_more_peers()); diff --git a/libtorrent/src/torrent_handle.cpp b/libtorrent/src/torrent_handle.cpp index aa517ac76..092d77c78 100755 --- a/libtorrent/src/torrent_handle.cpp +++ b/libtorrent/src/torrent_handle.cpp @@ -78,32 +78,90 @@ using boost::bind; using boost::mutex; using libtorrent::aux::session_impl; +#ifdef BOOST_NO_EXCEPTIONS + +#define TORRENT_FORWARD(call) \ + if (m_ses == 0) return; \ + TORRENT_ASSERT(m_chk); \ + session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); \ + mutex::scoped_lock l2(m_chk->m_mutex); \ + torrent* t = find_torrent(m_ses, m_chk, m_info_hash); \ + if (t == 0) return; \ + t->call + +#define TORRENT_FORWARD_RETURN(call, def) \ + if (m_ses == 0) return def; \ + TORRENT_ASSERT(m_chk); \ + session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); \ + mutex::scoped_lock l2(m_chk->m_mutex); \ + torrent* t = find_torrent(m_ses, m_chk, m_info_hash); \ + if (t == 0) return def; \ + return t->call + +#define TORRENT_FORWARD_RETURN2(call, def) \ + if (m_ses == 0) return def; \ + TORRENT_ASSERT(m_chk); \ + session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); \ + mutex::scoped_lock l2(m_chk->m_mutex); \ + torrent* t = find_torrent(m_ses, m_chk, m_info_hash); \ + if (t == 0) return def; \ + t->call + +#else + +#define TORRENT_FORWARD(call) \ + if (m_ses == 0) throw_invalid_handle(); \ + TORRENT_ASSERT(m_chk); \ + session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); \ + mutex::scoped_lock l2(m_chk->m_mutex); \ + torrent* t = find_torrent(m_ses, m_chk, m_info_hash); \ + if (t == 0) throw_invalid_handle(); \ + t->call + +#define TORRENT_FORWARD_RETURN(call, def) \ + if (m_ses == 0) throw_invalid_handle(); \ + TORRENT_ASSERT(m_chk); \ + session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); \ + mutex::scoped_lock l2(m_chk->m_mutex); \ + torrent* t = find_torrent(m_ses, m_chk, m_info_hash); \ + if (t == 0) return def; \ + return t->call + +#define TORRENT_FORWARD_RETURN2(call, def) \ + if (m_ses == 0) throw_invalid_handle(); \ + TORRENT_ASSERT(m_chk); \ + session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); \ + mutex::scoped_lock l2(m_chk->m_mutex); \ + torrent* t = find_torrent(m_ses, m_chk, m_info_hash); \ + if (t == 0) return def; \ + t->call + +#endif + namespace libtorrent { namespace fs = boost::filesystem; namespace { +#ifndef BOOST_NO_EXCEPTIONS void throw_invalid_handle() { throw invalid_handle(); } +#endif - boost::shared_ptr find_torrent( + torrent* find_torrent( session_impl* ses , aux::checker_impl* chk , sha1_hash const& hash) { aux::piece_checker_data* d = chk->find_torrent(hash); - if (d != 0) return d->torrent_ptr; + if (d != 0) return d->torrent_ptr.get(); boost::shared_ptr t = ses->find_torrent(hash).lock(); - if (t) return t; - - // throwing directly instead of calling - // the throw_invalid_handle() function - // avoids a warning in gcc - throw invalid_handle(); + if (t) return t.get(); + return 0; } } @@ -119,132 +177,68 @@ namespace libtorrent void torrent_handle::set_max_uploads(int max_uploads) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - TORRENT_ASSERT(max_uploads >= 2 || max_uploads == -1); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->set_max_uploads(max_uploads); + TORRENT_FORWARD(set_max_uploads(max_uploads)); } void torrent_handle::use_interface(const char* net_interface) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->use_interface(net_interface); + TORRENT_FORWARD(use_interface(net_interface)); } void torrent_handle::set_max_connections(int max_connections) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - TORRENT_ASSERT(max_connections >= 2 || max_connections == -1); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->set_max_connections(max_connections); + TORRENT_FORWARD(set_max_connections(max_connections)); } void torrent_handle::set_peer_upload_limit(tcp::endpoint ip, int limit) const { INVARIANT_CHECK; TORRENT_ASSERT(limit >= -1); - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->set_peer_upload_limit(ip, limit); + TORRENT_FORWARD(set_peer_upload_limit(ip, limit)); } void torrent_handle::set_peer_download_limit(tcp::endpoint ip, int limit) const { INVARIANT_CHECK; TORRENT_ASSERT(limit >= -1); - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->set_peer_download_limit(ip, limit); + TORRENT_FORWARD(set_peer_download_limit(ip, limit)); } void torrent_handle::set_upload_limit(int limit) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - TORRENT_ASSERT(limit >= -1); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->set_upload_limit(limit); + TORRENT_FORWARD(set_upload_limit(limit)); } int torrent_handle::upload_limit() const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - return find_torrent(m_ses, m_chk, m_info_hash)->upload_limit(); + TORRENT_FORWARD_RETURN(upload_limit(), 0); } void torrent_handle::set_download_limit(int limit) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - TORRENT_ASSERT(limit >= -1); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->set_download_limit(limit); + TORRENT_FORWARD(set_download_limit(limit)); } int torrent_handle::download_limit() const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - return find_torrent(m_ses, m_chk, m_info_hash)->download_limit(); + TORRENT_FORWARD_RETURN(download_limit(), 0); } void torrent_handle::move_storage( fs::path const& save_path) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->move_storage(save_path); + TORRENT_FORWARD(move_storage(save_path)); } void torrent_handle::add_extension( @@ -252,123 +246,62 @@ namespace libtorrent , void* userdata) { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - return find_torrent(m_ses, m_chk, m_info_hash)->add_extension(ext, userdata); + TORRENT_FORWARD(add_extension(ext, userdata)); } bool torrent_handle::has_metadata() const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - return find_torrent(m_ses, m_chk, m_info_hash)->valid_metadata(); + TORRENT_FORWARD_RETURN(valid_metadata(), false); } bool torrent_handle::is_seed() const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - return find_torrent(m_ses, m_chk, m_info_hash)->is_seed(); + TORRENT_FORWARD_RETURN(is_seed(), false); } bool torrent_handle::is_paused() const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - return find_torrent(m_ses, m_chk, m_info_hash)->is_paused(); + TORRENT_FORWARD_RETURN(is_paused(), false); } void torrent_handle::pause() const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->pause(); + TORRENT_FORWARD(pause()); } void torrent_handle::resume() const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->resume(); + TORRENT_FORWARD(resume()); } void torrent_handle::set_tracker_login(std::string const& name , std::string const& password) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->set_tracker_login(name, password); + TORRENT_FORWARD(resume()); } void torrent_handle::file_progress(std::vector& progress) { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - - aux::piece_checker_data* d = m_chk->find_torrent(m_info_hash); - if (d != 0) - { - if (!d->processing) - { - torrent_info const& info = d->torrent_ptr->torrent_file(); - progress.clear(); - progress.resize(info.num_files(), 0.f); - return; - } - d->torrent_ptr->file_progress(progress); - return; - } - - boost::shared_ptr t = m_ses->find_torrent(m_info_hash).lock(); - if (t) return t->file_progress(progress); - - throw_invalid_handle(); + TORRENT_FORWARD(file_progress(progress)); } torrent_status torrent_handle::status() const { INVARIANT_CHECK; - if (m_ses == 0) throw_invalid_handle(); + if (m_ses == 0) +#ifdef BOOST_NO_EXCEPTIONS + return torrent_status(); +#else + throw_invalid_handle(); +#endif TORRENT_ASSERT(m_chk); session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); @@ -396,107 +329,60 @@ namespace libtorrent boost::shared_ptr t = m_ses->find_torrent(m_info_hash).lock(); if (t) return t->status(); +#ifndef BOOST_NO_EXCEPTIONS throw_invalid_handle(); +#endif return torrent_status(); } void torrent_handle::set_sequenced_download_threshold(int threshold) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->set_sequenced_download_threshold(threshold); + TORRENT_FORWARD(set_sequenced_download_threshold(threshold)); } std::string torrent_handle::name() const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - return find_torrent(m_ses, m_chk, m_info_hash)->name(); + TORRENT_FORWARD_RETURN(name(), ""); } - void torrent_handle::piece_availability(std::vector& avail) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->piece_availability(avail); + TORRENT_FORWARD(piece_availability(avail)); } void torrent_handle::piece_priority(int index, int priority) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->set_piece_priority(index, priority); + TORRENT_FORWARD(set_piece_priority(index, priority)); } int torrent_handle::piece_priority(int index) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - return find_torrent(m_ses, m_chk, m_info_hash)->piece_priority(index); + TORRENT_FORWARD_RETURN(piece_priority(index), 0); } void torrent_handle::prioritize_pieces(std::vector const& pieces) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->prioritize_pieces(pieces); + TORRENT_FORWARD(prioritize_pieces(pieces)); } std::vector torrent_handle::piece_priorities() const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - std::vector ret; - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->piece_priorities(ret); + TORRENT_FORWARD_RETURN2(piece_priorities(ret), ret); return ret; } void torrent_handle::prioritize_files(std::vector const& files) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->prioritize_files(files); + TORRENT_FORWARD(prioritize_files(files)); } // ============ start deprecation =============== @@ -504,63 +390,33 @@ namespace libtorrent void torrent_handle::filter_piece(int index, bool filter) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->filter_piece(index, filter); + TORRENT_FORWARD(filter_piece(index, filter)); } void torrent_handle::filter_pieces(std::vector const& pieces) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->filter_pieces(pieces); + TORRENT_FORWARD(filter_pieces(pieces)); } bool torrent_handle::is_piece_filtered(int index) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - return find_torrent(m_ses, m_chk, m_info_hash)->is_piece_filtered(index); + TORRENT_FORWARD_RETURN(is_piece_filtered(index), false); } std::vector torrent_handle::filtered_pieces() const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - std::vector ret; - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->filtered_pieces(ret); + TORRENT_FORWARD_RETURN2(filtered_pieces(ret), ret); return ret; } void torrent_handle::filter_files(std::vector const& files) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->filter_files(files); + TORRENT_FORWARD(filter_files(files)); } // ============ end deprecation =============== @@ -569,111 +425,91 @@ namespace libtorrent std::vector const& torrent_handle::trackers() const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - return find_torrent(m_ses, m_chk, m_info_hash)->trackers(); + const static std::vector empty; + TORRENT_FORWARD_RETURN(trackers(), empty); } void torrent_handle::add_url_seed(std::string const& url) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->add_url_seed(url); + TORRENT_FORWARD(add_url_seed(url)); } void torrent_handle::remove_url_seed(std::string const& url) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->remove_url_seed(url); + TORRENT_FORWARD(remove_url_seed(url)); } std::set torrent_handle::url_seeds() const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - return find_torrent(m_ses, m_chk, m_info_hash)->url_seeds(); + const static std::set empty; + TORRENT_FORWARD_RETURN(url_seeds(), empty); } void torrent_handle::replace_trackers( std::vector const& urls) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->replace_trackers(urls); + TORRENT_FORWARD(replace_trackers(urls)); } torrent_info const& torrent_handle::get_torrent_info() const { INVARIANT_CHECK; - +#ifdef BOOST_NO_EXCEPTIONS + const static torrent_info empty; + if (m_ses == 0) return empty; +#else if (m_ses == 0) throw_invalid_handle(); +#endif TORRENT_ASSERT(m_chk); - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); mutex::scoped_lock l2(m_chk->m_mutex); - boost::shared_ptr t = find_torrent(m_ses, m_chk, m_info_hash); - if (!t->valid_metadata()) throw_invalid_handle(); + torrent* t = find_torrent(m_ses, m_chk, m_info_hash); + if (t == 0 || !t->valid_metadata()) +#ifdef BOOST_NO_EXCEPTIONS + return empty; +#else + throw_invalid_handle(); +#endif return t->torrent_file(); } bool torrent_handle::is_valid() const { INVARIANT_CHECK; - if (m_ses == 0) return false; TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); + session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); mutex::scoped_lock l2(m_chk->m_mutex); - aux::piece_checker_data* d = m_chk->find_torrent(m_info_hash); - if (d != 0) return true; - - { - boost::weak_ptr t = m_ses->find_torrent(m_info_hash); - if (!t.expired()) return true; - } - - return false; + torrent* t = find_torrent(m_ses, m_chk, m_info_hash); + return t; } entry torrent_handle::write_resume_data() const { INVARIANT_CHECK; - std::vector piece_index; - if (m_ses == 0) return entry(); + if (m_ses == 0) +#ifdef BOOST_NO_EXCEPTIONS + return entry(); +#else + throw_invalid_handle(); +#endif TORRENT_ASSERT(m_chk); session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); - boost::shared_ptr t = m_ses->find_torrent(m_info_hash).lock(); - if (!t) return entry(); + mutex::scoped_lock l2(m_chk->m_mutex); - if (!t->valid_metadata()) return entry(); + boost::shared_ptr t = m_ses->find_torrent(m_info_hash).lock(); + if (!t || !t->valid_metadata()) +#ifdef BOOST_NO_EXCEPTIONS + return entry(); +#else + throw_invalid_handle(); +#endif std::vector have_pieces = t->pieces(); @@ -748,6 +584,7 @@ namespace libtorrent } } + std::vector piece_index; t->filesystem().export_piece_map(piece_index, have_pieces); entry::list_type& slots = ret["slots"].list(); std::copy(piece_index.begin(), piece_index.end(), std::back_inserter(slots)); @@ -796,20 +633,19 @@ namespace libtorrent fs::path torrent_handle::save_path() const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - return find_torrent(m_ses, m_chk, m_info_hash)->save_path(); + TORRENT_FORWARD_RETURN(save_path(), fs::path()); } void torrent_handle::connect_peer(tcp::endpoint const& adr, int source) const { INVARIANT_CHECK; - if (m_ses == 0) throw_invalid_handle(); + if (m_ses == 0) +#ifdef BOOST_NO_EXCEPTIONS + return; +#else + throw_invalid_handle(); +#endif TORRENT_ASSERT(m_chk); session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); @@ -823,7 +659,12 @@ namespace libtorrent mutex::scoped_lock l2(m_chk->m_mutex); aux::piece_checker_data* d = m_chk->find_torrent(m_info_hash); - if (d == 0) throw_invalid_handle(); + if (d == 0) +#ifdef BOOST_NO_EXCEPTIONS + return; +#else + throw_invalid_handle(); +#endif d->peers.push_back(adr); return; } @@ -837,205 +678,55 @@ namespace libtorrent boost::posix_time::time_duration duration) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); - boost::shared_ptr t = m_ses->find_torrent(m_info_hash).lock(); - if (!t) throw_invalid_handle(); - - t->force_tracker_request(time_now() - + seconds(duration.total_seconds())); + TORRENT_FORWARD(force_tracker_request(time_now() + seconds(duration.total_seconds()))); } void torrent_handle::force_reannounce() const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); - boost::shared_ptr t = m_ses->find_torrent(m_info_hash).lock(); - if (!t) throw_invalid_handle(); - - t->force_tracker_request(); + TORRENT_FORWARD(force_tracker_request()); } void torrent_handle::scrape_tracker() const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); - boost::shared_ptr t = m_ses->find_torrent(m_info_hash).lock(); - if (!t) throw_invalid_handle(); - - t->scrape_tracker(); + TORRENT_FORWARD(scrape_tracker()); } void torrent_handle::set_ratio(float ratio) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - + TORRENT_ASSERT(ratio >= 0.f); if (ratio < 1.f && ratio > 0.f) ratio = 1.f; - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->set_ratio(ratio); + TORRENT_FORWARD(set_ratio(ratio)); } #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES void torrent_handle::resolve_countries(bool r) { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - find_torrent(m_ses, m_chk, m_info_hash)->resolve_countries(r); + TORRENT_FORWARD(resolve_countries(r)); } bool torrent_handle::resolve_countries() const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex); - mutex::scoped_lock l2(m_chk->m_mutex); - return find_torrent(m_ses, m_chk, m_info_hash)->resolving_countries(); + TORRENT_FORWARD_RETURN(resolving_countries(), false); } #endif void torrent_handle::get_peer_info(std::vector& v) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - v.clear(); - - session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); - - boost::shared_ptr t = m_ses->find_torrent(m_info_hash).lock(); - if (!t) return; - - for (torrent::const_peer_iterator i = t->begin(); - i != t->end(); ++i) - { - peer_connection* peer = *i; - - // incoming peers that haven't finished the handshake should - // not be included in this list - if (peer->associated_torrent().expired()) continue; - - v.push_back(peer_info()); - peer_info& p = v.back(); - - peer->get_peer_info(p); -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - if (t->resolving_countries()) - t->resolve_peer_country(intrusive_ptr(peer)); -#endif - } + TORRENT_FORWARD(get_peer_info(v)); } void torrent_handle::get_download_queue(std::vector& queue) const { INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - TORRENT_ASSERT(m_chk); - - session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); - boost::shared_ptr t = m_ses->find_torrent(m_info_hash).lock(); - - queue.clear(); - if (!t) return; - if (!t->valid_metadata()) return; - // if we're a seed, the piece picker has been removed - if (t->is_seed()) return; - - const piece_picker& p = t->picker(); - - const std::vector& q - = p.get_download_queue(); - - int block_size = t->block_size(); - - for (std::vector::const_iterator i - = q.begin(); i != q.end(); ++i) - { - partial_piece_info pi; - pi.piece_state = (partial_piece_info::state_t)i->state; - pi.blocks_in_piece = p.blocks_in_piece(i->index); - pi.finished = (int)i->finished; - pi.writing = (int)i->writing; - pi.requested = (int)i->requested; - int piece_size = t->torrent_file().piece_size(i->index); - for (int j = 0; j < pi.blocks_in_piece; ++j) - { - block_info& bi = pi.blocks[j]; - bi.state = i->info[j].state; - bi.block_size = j < pi.blocks_in_piece - 1 ? block_size - : piece_size - (j * block_size); - bool complete = bi.state == block_info::writing - || bi.state == block_info::finished; - if (i->info[j].peer == 0) - { - bi.peer = tcp::endpoint(); - bi.bytes_progress = complete ? bi.block_size : 0; - } - else - { - policy::peer* p = static_cast(i->info[j].peer); - if (p->connection) - { - bi.peer = p->connection->remote(); - if (bi.state == block_info::requested) - { - boost::optional pbp - = p->connection->downloading_piece_progress(); - if (pbp && pbp->piece_index == i->index && pbp->block_index == j) - { - bi.bytes_progress = pbp->bytes_downloaded; - TORRENT_ASSERT(bi.bytes_progress <= bi.block_size); - } - else - { - bi.bytes_progress = 0; - } - } - else - { - bi.bytes_progress = complete ? bi.block_size : 0; - } - } - else - { - bi.peer = p->ip; - bi.bytes_progress = complete ? bi.block_size : 0; - } - } - - pi.blocks[j].num_peers = i->info[j].num_peers; - } - pi.piece_index = i->index; - queue.push_back(pi); - } + TORRENT_FORWARD(get_download_queue(queue)); } } diff --git a/libtorrent/src/torrent_info.cpp b/libtorrent/src/torrent_info.cpp index 3d30dadd5..b89510f9f 100755 --- a/libtorrent/src/torrent_info.cpp +++ b/libtorrent/src/torrent_info.cpp @@ -165,7 +165,7 @@ namespace { target.size = dict["length"].integer(); target.path = root_dir; - + target.file_base = 0; // prefer the name.utf-8 // because if it exists, it is more @@ -824,20 +824,19 @@ namespace libtorrent m_nodes.push_back(node); } - bool torrent_info::remap_files(std::vector > const& map) + bool torrent_info::remap_files(std::vector const& map) { - typedef std::vector > files_t; - size_type offset = 0; m_remapped_files.resize(map.size()); for (int i = 0; i < int(map.size()); ++i) { file_entry& fe = m_remapped_files[i]; - fe.path = map[i].first; + fe.path = map[i].path; fe.offset = offset; - fe.size = map[i].second; + fe.size = map[i].size; + fe.file_base = map[i].file_base; + fe.orig_path.reset(); offset += fe.size; } if (offset != total_size()) @@ -846,6 +845,26 @@ namespace libtorrent return false; } +#ifndef NDEBUG + std::vector map2(m_remapped_files); + std::sort(map2.begin(), map2.end() + , bind(&file_entry::file_base, _1) < bind(&file_entry::file_base, _2)); + std::stable_sort(map2.begin(), map2.end() + , bind(&file_entry::path, _1) < bind(&file_entry::path, _2)); + fs::path last_path; + size_type last_end = 0; + for (std::vector::iterator i = map2.begin(), end(map2.end()); + i != end; ++i) + { + if (last_path == i->path) + { + assert(last_end <= i->file_base); + } + last_end = i->file_base + i->size; + last_path = i->path; + } +#endif + return true; } @@ -871,7 +890,7 @@ namespace libtorrent { file_slice f; f.file_index = counter; - f.offset = file_offset; + f.offset = file_offset + file_iter->file_base; f.size = (std::min)(file_iter->size - file_offset, (size_type)size); size -= f.size; file_offset += f.size; diff --git a/libtorrent/src/web_peer_connection.cpp b/libtorrent/src/web_peer_connection.cpp index 21208454e..71ce2d430 100755 --- a/libtorrent/src/web_peer_connection.cpp +++ b/libtorrent/src/web_peer_connection.cpp @@ -306,10 +306,12 @@ namespace libtorrent namespace { - bool range_contains(peer_request const& range, peer_request const& req) + bool range_contains(peer_request const& range, peer_request const& req, int piece_size) { - return range.start <= req.start - && range.start + range.length >= req.start + req.length; + size_type range_start = size_type(range.piece) * piece_size + range.start; + size_type req_start = size_type(req.piece) * piece_size + req.start; + return range_start <= req_start + && range_start + range.length >= req_start + req.length; } } @@ -358,7 +360,11 @@ namespace libtorrent && !(m_parser.status_code() >= 300 // redirect && m_parser.status_code() < 400)) { - // we should not try this server again. + if (m_parser.status_code() == 503) + { + // temporarily unavailable, retry later + t->retry_url_seed(m_url); + } t->remove_url_seed(m_url); std::string error_msg = boost::lexical_cast(m_parser.status_code()) + " " + m_parser.message(); @@ -470,6 +476,9 @@ namespace libtorrent } } +// std::cerr << "REQUESTS: m_requests: " << m_requests.size() +// << " file_requests: " << m_file_requests.size() << std::endl; + torrent_info const& info = t->torrent_file(); if (m_requests.empty() || m_file_requests.empty()) @@ -484,16 +493,13 @@ namespace libtorrent size_type rs = size_type(in_range.piece) * info.piece_length() + in_range.start; size_type re = rs + in_range.length; size_type fs = size_type(front_request.piece) * info.piece_length() + front_request.start; +/* size_type fe = fs + front_request.length; - if (fs < rs || fe > re) - { - throw std::runtime_error("invalid range in HTTP response"); - } - // skip the http header and the blocks we've already read. The - // http_body.begin is now in sync with the request at the front - // of the request queue -// TORRENT_ASSERT(in_range.start - int(m_piece.size()) <= front_request.start); + std::cerr << "RANGE: r = (" << rs << ", " << re << " ) " + "f = (" << fs << ", " << fe << ") " + "file_index = " << file_index << " received_body = " << m_received_body << std::endl; +*/ // the http response body consists of 3 parts // 1. the middle of a block or the ending of a block @@ -501,14 +507,20 @@ namespace libtorrent // 3. the start of a block // in that order, these parts are parsed. - bool range_overlaps_request = in_range.start + in_range.length - > front_request.start + int(m_piece.size()); + bool range_overlaps_request = re > fs + int(m_piece.size()); + + if (!range_overlaps_request) + { + // this means the end of the incoming request ends _before_ the + // first expected byte (fs + m_piece.size()) + throw std::runtime_error("invalid range in HTTP response"); + } // if the request is contained in the range (i.e. the entire request // fits in the range) we should not start a partial piece, since we soon // will receive enough to call incoming_piece() and pass the read buffer // directly (in the next loop below). - if (range_overlaps_request && !range_contains(in_range, front_request)) + if (range_overlaps_request && !range_contains(in_range, front_request, info.piece_length())) { // the start of the next block to receive is stored // in m_piece. We need to append the rest of that @@ -549,7 +561,7 @@ namespace libtorrent // report all received blocks to the bittorrent engine while (!m_requests.empty() - && range_contains(in_range, m_requests.front()) + && range_contains(in_range, m_requests.front(), info.piece_length()) && recv_buffer.left() >= m_requests.front().length) { peer_request r = m_requests.front(); diff --git a/src/deluge_core.cpp b/src/deluge_core.cpp index 9238a2c03..846a49fbe 100644 --- a/src/deluge_core.cpp +++ b/src/deluge_core.cpp @@ -273,13 +273,15 @@ boost::filesystem::path const& save_path) return (new_torrent.unique_ID); } catch (invalid_encoding&) - { - printf("invalid encoding...bad torrent\n"); - } + { RAISE_PTR(InvalidEncodingError, ""); } catch (invalid_handle&) - { - printf("invalid handle. something bad happened in libtorrent\n"); - } + { printf("invalid handle error on add_torrent"); } + catch (invalid_torrent_file&) + { RAISE_PTR(InvalidTorrentError, ""); } + catch (boost::filesystem::filesystem_error&) + { RAISE_PTR(FilesystemError, ""); } + catch (duplicate_torrent&) + { RAISE_PTR(DuplicateTorrentError, "libtorrent reports this is a duplicate torrent"); } catch (...) {} } @@ -1999,35 +2001,6 @@ static PyObject *torrent_add_url_seed(PyObject *self, PyObject *args) Py_INCREF(Py_None); return Py_None; } -static PyObject *torrent_remap_files(PyObject *self, PyObject *args) -{ - python_long unique_ID; - PyObject *file_path_object; - PyObject *file_size_object; - - if (!PyArg_ParseTuple(args, "iOO", &unique_ID, &file_path_object, &file_size_object)) - return NULL; - long index = get_index_from_unique_ID(unique_ID); - if (PyErr_Occurred()) - return NULL; - - if (M_torrents->at(index).handle.is_valid()){ - - std::vector > remap_vector; - for (long i = 0; i < PyList_Size(file_size_object); i++) { - remap_vector.push_back(std::make_pair(PyString_AsString(PyList_GetItem(file_path_object, i)), PyInt_AsLong(PyList_GetItem(file_size_object, i)))); - } - torrent_info t = M_torrents->at(index).handle.get_torrent_info(); - bool ret = t.remap_files(remap_vector); - if (ret){ - printf("remap worked!\n"); - } - else{ - printf("remap failed!\n"); - } -} - Py_INCREF(Py_None); return Py_None; -} static PyObject *torrent_scrape_tracker(PyObject *self, PyObject *args) { python_long unique_ID; @@ -2112,7 +2085,6 @@ static PyMethodDef deluge_core_methods[] = {"get_piece_info", torrent_get_piece_info, METH_VARARGS, "."}, {"get_all_piece_info", torrent_get_all_piece_info, METH_VARARGS, "."}, {"get_file_piece_range", torrent_get_file_piece_range, METH_VARARGS, "."}, - {"remap_files", torrent_remap_files, METH_VARARGS, "."}, {"scrape_tracker", torrent_scrape_tracker, METH_VARARGS, "."}, {NULL} };