diff --git a/libtorrent/include/libtorrent/aux_/session_impl.hpp b/libtorrent/include/libtorrent/aux_/session_impl.hpp index 606a38930..e0962bf06 100644 --- a/libtorrent/include/libtorrent/aux_/session_impl.hpp +++ b/libtorrent/include/libtorrent/aux_/session_impl.hpp @@ -284,8 +284,8 @@ namespace libtorrent { torrent* t = c.associated_torrent().lock().get(); assert(t); - t->unchoke_peer(c); - ++m_num_unchoked; + if (t->unchoke_peer(c)) + ++m_num_unchoked; } session_status status() const; diff --git a/libtorrent/include/libtorrent/bandwidth_manager.hpp b/libtorrent/include/libtorrent/bandwidth_manager.hpp index f4663f39a..c46772bd8 100644 --- a/libtorrent/include/libtorrent/bandwidth_manager.hpp +++ b/libtorrent/include/libtorrent/bandwidth_manager.hpp @@ -49,6 +49,8 @@ using boost::shared_ptr; using boost::intrusive_ptr; using boost::bind; +//#define TORRENT_VERBOSE_BANDWIDTH_LIMIT + namespace libtorrent { // the maximum block of bandwidth quota to @@ -237,8 +239,10 @@ struct bandwidth_manager i = j; } } - - if (m_queue.size() == 1) hand_out_bandwidth(); +#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT + std::cerr << " req_bandwidht. m_queue.size() = " << m_queue.size() << std::endl; +#endif + if (!m_queue.empty()) hand_out_bandwidth(); } #ifndef NDEBUG @@ -337,11 +341,18 @@ private: // available bandwidth to hand out int amount = limit - m_current_quota; +#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT + std::cerr << " hand_out_bandwidht. m_queue.size() = " << m_queue.size() + << " amount = " << amount + << " limit = " << limit + << " m_current_quota = " << m_current_quota << std::endl; +#endif + while (!m_queue.empty() && amount > 0) { assert(amount == limit - m_current_quota); bw_queue_entry qe = m_queue.front(); - assert(qe.max_block_size > 0); + assert(qe.max_block_size > 0); m_queue.pop_front(); shared_ptr t = qe.peer->associated_torrent().lock(); @@ -380,7 +391,7 @@ private: if (block_size < min_bandwidth_block_size) { - block_size = min_bandwidth_block_size; + block_size = (std::min)(int(min_bandwidth_block_size), m_limit); } else if (block_size > max_bandwidth_block_size) { @@ -401,6 +412,9 @@ 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; +#endif if (amount < block_size / 2) { m_queue.push_front(qe); @@ -463,4 +477,3 @@ private: #endif - diff --git a/libtorrent/include/libtorrent/torrent_info.hpp b/libtorrent/include/libtorrent/torrent_info.hpp index a2d6c4ef9..795289bf4 100755 --- a/libtorrent/include/libtorrent/torrent_info.hpp +++ b/libtorrent/include/libtorrent/torrent_info.hpp @@ -71,7 +71,7 @@ namespace libtorrent size_type offset; // the offset of this file inside the torrent size_type size; // the size of this file // if the path was incorrectly encoded, this is - // the origianal corrupt encoded string. It is + // the original corrupt encoded string. It is // preserved in order to be able to reproduce // the correct info-hash boost::shared_ptr orig_path; @@ -115,8 +115,12 @@ namespace libtorrent void add_file(fs::path file, size_type size); void add_url_seed(std::string const& url); - std::vector map_block(int piece, size_type offset, int size) const; - peer_request map_file(int file, size_type offset, int size) const; + bool remap_files(std::vector > const& map); + + std::vector map_block(int piece, size_type offset + , int size, bool storage = false) const; + peer_request map_file(int file, size_type offset, int size + , bool storage = false) const; std::vector const& url_seeds() const { @@ -128,15 +132,60 @@ namespace libtorrent typedef std::vector::const_reverse_iterator reverse_file_iterator; // list the files in the torrent file - file_iterator begin_files() const { return m_files.begin(); } - file_iterator end_files() const { return m_files.end(); } - reverse_file_iterator rbegin_files() const { return m_files.rbegin(); } - reverse_file_iterator rend_files() const { return m_files.rend(); } + file_iterator begin_files(bool storage = false) const + { + if (!storage || m_remapped_files.empty()) + return m_files.begin(); + else + return m_remapped_files.begin(); + } - int num_files() const - { assert(m_piece_length > 0); return (int)m_files.size(); } - const file_entry& file_at(int index) const - { assert(index >= 0 && index < (int)m_files.size()); return m_files[index]; } + file_iterator end_files(bool storage = false) const + { + if (!storage || m_remapped_files.empty()) + return m_files.end(); + else + return m_remapped_files.end(); + } + + reverse_file_iterator rbegin_files(bool storage = false) const + { + if (!storage || m_remapped_files.empty()) + return m_files.rbegin(); + else + return m_remapped_files.rbegin(); + } + + reverse_file_iterator rend_files(bool storage = false) const + { + if (!storage || m_remapped_files.empty()) + return m_files.rend(); + else + return m_remapped_files.rend(); + } + + int num_files(bool storage = false) const + { + assert(m_piece_length > 0); + if (!storage || m_remapped_files.empty()) + return (int)m_files.size(); + else + return (int)m_remapped_files.size(); + } + + const file_entry& file_at(int index, bool storage = false) const + { + if (!storage || m_remapped_files.empty()) + { + assert(index >= 0 && index < (int)m_files.size()); + return m_files[index]; + } + else + { + assert(index >= 0 && index < (int)m_remapped_files.size()); + return m_remapped_files[index]; + } + } const std::vector& trackers() const { return m_urls; } @@ -218,6 +267,13 @@ namespace libtorrent // the list of files that this torrent consists of std::vector m_files; + // 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 + // on disk. This is only used when reading and + // writing the disk. + std::vector m_remapped_files; + nodes_t m_nodes; // the sum of all filesizes diff --git a/libtorrent/src/identify_client.cpp b/libtorrent/src/identify_client.cpp index 26ddb51dc..7fa808f20 100755 --- a/libtorrent/src/identify_client.cpp +++ b/libtorrent/src/identify_client.cpp @@ -184,6 +184,7 @@ namespace , {"SB", "Swiftbit"} , {"SN", "ShareNet"} , {"SS", "SwarmScope"} + , {"ST", "SymTorrent"} , {"SZ", "Shareaza"} , {"S~", "Shareaza (beta)"} , {"T", "BitTornado"} @@ -194,12 +195,57 @@ namespace , {"U", "UPnP"} , {"UL", "uLeecher"} , {"UT", "uTorrent"} + , {"XL", "Xunlei"} , {"XT", "XanTorrent"} , {"XX", "Xtorrent"} , {"ZT", "ZipTorrent"} , {"lt", "rTorrent"} , {"pX", "pHoeniX"} , {"qB", "qBittorrent"} + , {"st", "SharkTorrent"} + }; + + struct generic_map_entry + { + int offset; + char const* id; + char const* name; + }; + // non-standard names + generic_map_entry generic_mappings[] = + { + {0, "Deadman Walking-", "Deadman"} + , {5, "Azureus", "Azureus 2.0.3.2"} + , {0, "DansClient", "XanTorrent"} + , {4, "btfans", "SimpleBT"} + , {0, "PRC.P---", "Bittorrent Plus! II"} + , {0, "P87.P---", "Bittorrent Plus!"} + , {0, "S587Plus", "Bittorrent Plus!"} + , {0, "martini", "Martini Man"} + , {0, "Plus---", "Bittorrent Plus"} + , {0, "turbobt", "TurboBT"} + , {0, "a00---0", "Swarmy"} + , {0, "a02---0", "Swarmy"} + , {0, "T00---0", "Teeweety"} + , {0, "BTDWV-", "Deadman Walking"} + , {2, "BS", "BitSpirit"} + , {0, "Pando-", "Pando"} + , {0, "LIME", "LimeWire"} + , {0, "btuga", "BTugaXP"} + , {0, "oernu", "BTugaXP"} + , {0, "Mbrst", "Burst!"} + , {0, "PEERAPP", "PeerApp"} + , {0, "Plus", "Plus!"} + , {0, "-Qt-", "Qt"} + , {0, "exbc", "BitComet"} + , {0, "DNA", "BitTorrent DNA"} + , {0, "-G3", "G3 Torrent"} + , {0, "-FG", "FlashGet"} + , {0, "-ML", "MLdonkey"} + , {0, "XBT", "XBT"} + , {0, "OP", "Opera"} + , {2, "RS", "Rufus"} + , {0, "AZ2500BT", "BitTyrant"} }; bool compare_id(map_entry const& lhs, map_entry const& rhs) @@ -281,30 +327,13 @@ namespace libtorrent // non standard encodings // ---------------------- - if (find_string(PID, "Deadman Walking-")) return "Deadman"; - if (find_string(PID + 5, "Azureus")) return "Azureus 2.0.3.2"; - if (find_string(PID, "DansClient")) return "XanTorrent"; - if (find_string(PID + 4, "btfans")) return "SimpleBT"; - if (find_string(PID, "PRC.P---")) return "Bittorrent Plus! II"; - if (find_string(PID, "P87.P---")) return "Bittorrent Plus!"; - if (find_string(PID, "S587Plus")) return "Bittorrent Plus!"; - if (find_string(PID, "martini")) return "Martini Man"; - if (find_string(PID, "Plus---")) return "Bittorrent Plus"; - if (find_string(PID, "turbobt")) return "TurboBT"; - if (find_string(PID, "a00---0")) return "Swarmy"; - if (find_string(PID, "a02---0")) return "Swarmy"; - if (find_string(PID, "T00---0")) return "Teeweety"; - if (find_string(PID, "BTDWV-")) return "Deadman Walking"; - if (find_string(PID + 2, "BS")) return "BitSpirit"; - if (find_string(PID, "btuga")) return "BTugaXP"; - if (find_string(PID, "oernu")) return "BTugaXP"; - if (find_string(PID, "Mbrst")) return "Burst!"; - if (find_string(PID, "Plus")) return "Plus!"; - if (find_string(PID, "-Qt-")) return "Qt"; - if (find_string(PID, "exbc")) return "BitComet"; - if (find_string(PID, "-G3")) return "G3 Torrent"; - if (find_string(PID, "XBT")) return "XBT"; - if (find_string(PID, "OP")) return "Opera"; + int num_generic_mappings = sizeof(generic_mappings) / sizeof(generic_mappings[0]); + + for (int i = 0; i < num_generic_mappings; ++i) + { + generic_map_entry const& e = generic_mappings[i]; + if (find_string(PID + e.offset, e.id)) return e.name; + } if (find_string(PID, "-BOW") && PID[7] == '-') return "Bits on Wheels " + std::string(PID + 4, PID + 7); diff --git a/libtorrent/src/kademlia/dht_tracker.cpp b/libtorrent/src/kademlia/dht_tracker.cpp index fd2696171..c9908a163 100644 --- a/libtorrent/src/kademlia/dht_tracker.cpp +++ b/libtorrent/src/kademlia/dht_tracker.cpp @@ -978,4 +978,3 @@ namespace libtorrent { namespace dht }} - diff --git a/libtorrent/src/peer_connection.cpp b/libtorrent/src/peer_connection.cpp index 7b4975987..c6be880ad 100755 --- a/libtorrent/src/peer_connection.cpp +++ b/libtorrent/src/peer_connection.cpp @@ -189,7 +189,7 @@ namespace libtorrent , m_download_limit(bandwidth_limit::inf) , m_peer_info(peerinfo) , m_speed(slow) - , m_connection_ticket(-1) + , m_connection_ticket(-1) , m_remote_bytes_dled(0) , m_remote_dl_rate(0) , m_remote_dl_update(time_now()) diff --git a/libtorrent/src/piece_picker.cpp b/libtorrent/src/piece_picker.cpp index 87c95729b..d44dd1435 100755 --- a/libtorrent/src/piece_picker.cpp +++ b/libtorrent/src/piece_picker.cpp @@ -1699,3 +1699,4 @@ namespace libtorrent } } + diff --git a/libtorrent/src/policy.cpp b/libtorrent/src/policy.cpp index 90f562b77..5683b74e5 100755 --- a/libtorrent/src/policy.cpp +++ b/libtorrent/src/policy.cpp @@ -1530,4 +1530,3 @@ namespace libtorrent } } - diff --git a/libtorrent/src/session_impl.cpp b/libtorrent/src/session_impl.cpp index 4d45092cd..125664302 100755 --- a/libtorrent/src/session_impl.cpp +++ b/libtorrent/src/session_impl.cpp @@ -976,6 +976,8 @@ namespace detail // if we should not make any more connections // attempts this tick, abort if (max_connections == 0) break; + // maintain the global limit on number of connections + if (num_connections() >= m_max_connections) break; } } diff --git a/libtorrent/src/storage.cpp b/libtorrent/src/storage.cpp index 8d738c669..64f601927 100755 --- a/libtorrent/src/storage.cpp +++ b/libtorrent/src/storage.cpp @@ -247,8 +247,8 @@ namespace libtorrent { p = complete(p); std::vector > sizes; - for (torrent_info::file_iterator i = t.begin_files(); - i != t.end_files(); ++i) + for (torrent_info::file_iterator i = t.begin_files(true); + i != t.end_files(true); ++i) { size_type size = 0; std::time_t time = 0; @@ -287,7 +287,7 @@ namespace libtorrent , bool compact_mode , std::string* error) { - if ((int)sizes.size() != t.num_files()) + if ((int)sizes.size() != t.num_files(true)) { if (error) *error = "mismatching number of files"; return false; @@ -296,8 +296,8 @@ namespace libtorrent std::vector >::const_iterator s = sizes.begin(); - for (torrent_info::file_iterator i = t.begin_files(); - i != t.end_files(); ++i, ++s) + for (torrent_info::file_iterator i = t.begin_files(true); + i != t.end_files(true); ++i, ++s) { size_type size = 0; std::time_t time = 0; @@ -342,50 +342,14 @@ namespace libtorrent return true; } - struct thread_safe_storage - { - thread_safe_storage(std::size_t n) - : slots(n, false) - {} - - boost::mutex mutex; - boost::condition condition; - std::vector slots; - }; - - struct slot_lock - { - slot_lock(thread_safe_storage& s, int slot_) - : storage_(s) - , slot(slot_) - { - assert(slot_>=0 && slot_ < (int)s.slots.size()); - boost::mutex::scoped_lock lock(storage_.mutex); - - while (storage_.slots[slot]) - storage_.condition.wait(lock); - storage_.slots[slot] = true; - } - - ~slot_lock() - { - storage_.slots[slot] = false; - storage_.condition.notify_all(); - } - - thread_safe_storage& storage_; - int slot; - }; - - class storage : public storage_interface, thread_safe_storage, boost::noncopyable + class storage : public storage_interface, boost::noncopyable { public: storage(torrent_info const& info, fs::path const& path, file_pool& fp) - : thread_safe_storage(info.num_pieces()) - , m_info(info) + : m_info(info) , m_files(fp) { - assert(info.begin_files() != info.end_files()); + assert(info.begin_files(true) != info.end_files(true)); m_save_path = fs::complete(path); assert(m_save_path.is_complete()); } @@ -448,8 +412,8 @@ namespace libtorrent { // first, create all missing directories fs::path last_path; - for (torrent_info::file_iterator file_iter = m_info.begin_files(), - end_iter = m_info.end_files(); file_iter != end_iter; ++file_iter) + for (torrent_info::file_iterator file_iter = m_info.begin_files(true), + end_iter = m_info.end_files(true); file_iter != end_iter; ++file_iter) { fs::path dir = (m_save_path / file_iter->path).branch_path(); @@ -546,11 +510,11 @@ namespace libtorrent if (seed) { - if (m_info.num_files() != (int)file_sizes.size()) + if (m_info.num_files(true) != (int)file_sizes.size()) { error = "the number of files does not match the torrent (num: " + boost::lexical_cast(file_sizes.size()) + " actual: " - + boost::lexical_cast(m_info.num_files()) + ")"; + + boost::lexical_cast(m_info.num_files(true)) + ")"; return false; } @@ -558,8 +522,8 @@ namespace libtorrent fs = file_sizes.begin(); // the resume data says we have the entire torrent // make sure the file sizes are the right ones - for (torrent_info::file_iterator i = m_info.begin_files() - , end(m_info.end_files()); i != end; ++i, ++fs) + for (torrent_info::file_iterator i = m_info.begin_files(true) + , end(m_info.end_files(true)); i != end; ++i, ++fs) { if (i->size != fs->first) { @@ -722,11 +686,9 @@ namespace libtorrent assert(offset < m_info.piece_size(slot)); assert(size > 0); - slot_lock lock(*this, slot); - #ifndef NDEBUG std::vector slices - = m_info.map_block(slot, offset, size); + = m_info.map_block(slot, offset, size, true); assert(!slices.empty()); #endif @@ -737,7 +699,7 @@ namespace libtorrent size_type file_offset = start; std::vector::const_iterator file_iter; - for (file_iter = m_info.begin_files();;) + for (file_iter = m_info.begin_files(true);;) { if (file_offset < file_iter->size) break; @@ -795,7 +757,7 @@ namespace libtorrent assert(int(slices.size()) > counter); size_type slice_size = slices[counter].size; assert(slice_size == read_bytes); - assert(m_info.file_at(slices[counter].file_index).path + assert(m_info.file_at(slices[counter].file_index, true).path == file_iter->path); #endif @@ -849,11 +811,9 @@ namespace libtorrent assert(offset >= 0); assert(size > 0); - slot_lock lock(*this, slot); - #ifndef NDEBUG std::vector slices - = m_info.map_block(slot, offset, size); + = m_info.map_block(slot, offset, size, true); assert(!slices.empty()); #endif @@ -863,14 +823,14 @@ namespace libtorrent size_type file_offset = start; std::vector::const_iterator file_iter; - for (file_iter = m_info.begin_files();;) + for (file_iter = m_info.begin_files(true);;) { if (file_offset < file_iter->size) break; file_offset -= file_iter->size; ++file_iter; - assert(file_iter != m_info.end_files()); + assert(file_iter != m_info.end_files(true)); } fs::path p(m_save_path / file_iter->path); @@ -914,7 +874,7 @@ namespace libtorrent { assert(int(slices.size()) > counter); assert(slices[counter].size == write_bytes); - assert(m_info.file_at(slices[counter].file_index).path + assert(m_info.file_at(slices[counter].file_index, true).path == file_iter->path); assert(buf_pos >= 0); @@ -942,7 +902,7 @@ namespace libtorrent #endif ++file_iter; - assert(file_iter != m_info.end_files()); + assert(file_iter != m_info.end_files(true)); fs::path p = m_save_path / file_iter->path; file_offset = 0; out = m_files.open_file( @@ -1906,8 +1866,8 @@ namespace libtorrent // find the file that failed, and skip all the blocks in that file size_type file_offset = 0; size_type current_offset = m_current_slot * m_info.piece_length(); - for (torrent_info::file_iterator i = m_info.begin_files(); - i != m_info.end_files(); ++i) + for (torrent_info::file_iterator i = m_info.begin_files(true); + i != m_info.end_files(true); ++i) { file_offset += i->size; if (file_offset > current_offset) break; diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index dc42bb340..9cd2c277c 100755 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -1838,6 +1838,7 @@ namespace libtorrent #endif assert(want_more_peers()); + assert(m_ses.num_connections() < m_ses.max_connections()); tcp::endpoint const& a(peerinfo->ip); assert((m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked) == 0); @@ -2025,9 +2026,9 @@ namespace libtorrent , boost::intrusive_ptr const& p , bool non_prioritized) { - assert(m_bandwidth_limit[channel].throttle() > 0); + assert(m_bandwidth_limit[channel].throttle() > 0); int block_size = m_bandwidth_limit[channel].throttle() / 10; - if (block_size <= 0) block_size = 1; + if (block_size <= 0) block_size = 1; if (m_bandwidth_limit[channel].max_assignable() > 0) { diff --git a/libtorrent/src/torrent_handle.cpp b/libtorrent/src/torrent_handle.cpp index 9dc1e6d26..3cf1f2bac 100755 --- a/libtorrent/src/torrent_handle.cpp +++ b/libtorrent/src/torrent_handle.cpp @@ -89,26 +89,22 @@ namespace libtorrent throw invalid_handle(); } - template - Ret call_member( + boost::shared_ptr find_torrent( session_impl* ses , aux::checker_impl* chk - , sha1_hash const& hash - , F f) + , sha1_hash const& hash) { if (ses == 0) throw_invalid_handle(); if (chk) { - mutex::scoped_lock l(chk->m_mutex); aux::piece_checker_data* d = chk->find_torrent(hash); - if (d != 0) return f(*d->torrent_ptr); + if (d != 0) return d->torrent_ptr; } { - session_impl::mutex_t::scoped_lock l(ses->m_mutex); boost::shared_ptr t = ses->find_torrent(hash).lock(); - if (t) return f(*t); + if (t) return t; } // throwing directly instead of calling @@ -133,16 +129,18 @@ namespace libtorrent assert(max_uploads >= 2 || max_uploads == -1); - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::set_max_uploads, _1, max_uploads)); + 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); } void torrent_handle::use_interface(const char* net_interface) const { INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::use_interface, _1, net_interface)); + 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); } void torrent_handle::set_max_connections(int max_connections) const @@ -151,8 +149,9 @@ namespace libtorrent assert(max_connections >= 2 || max_connections == -1); - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::set_max_connections, _1, max_connections)); + 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); } void torrent_handle::set_peer_upload_limit(tcp::endpoint ip, int limit) const @@ -160,8 +159,9 @@ namespace libtorrent INVARIANT_CHECK; assert(limit >= -1); - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::set_peer_upload_limit, _1, ip, limit)); + 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); } void torrent_handle::set_peer_download_limit(tcp::endpoint ip, int limit) const @@ -169,8 +169,9 @@ namespace libtorrent INVARIANT_CHECK; assert(limit >= -1); - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::set_peer_download_limit, _1, ip, limit)); + 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); } void torrent_handle::set_upload_limit(int limit) const @@ -179,15 +180,17 @@ namespace libtorrent assert(limit >= -1); - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::set_upload_limit, _1, limit)); + 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); } int torrent_handle::upload_limit() const { INVARIANT_CHECK; - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::upload_limit, _1)); + 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(); } void torrent_handle::set_download_limit(int limit) const @@ -196,15 +199,18 @@ namespace libtorrent assert(limit >= -1); - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::set_download_limit, _1, limit)); + 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); } int torrent_handle::download_limit() const { INVARIANT_CHECK; - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::download_limit, _1)); + + 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(); } void torrent_handle::move_storage( @@ -212,48 +218,54 @@ namespace libtorrent { INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::move_storage, _1, save_path)); + 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); } bool torrent_handle::has_metadata() const { INVARIANT_CHECK; - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::valid_metadata, _1)); + 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(); } bool torrent_handle::is_seed() const { INVARIANT_CHECK; - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::is_seed, _1)); + 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(); } bool torrent_handle::is_paused() const { INVARIANT_CHECK; - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::is_paused, _1)); + 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(); } void torrent_handle::pause() const { INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::pause, _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)->pause(); } void torrent_handle::resume() const { INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::resume, _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)->resume(); } void torrent_handle::set_tracker_login(std::string const& name @@ -261,8 +273,9 @@ namespace libtorrent { INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::set_tracker_login, _1, name, password)); + 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); } void torrent_handle::file_progress(std::vector& progress) @@ -342,15 +355,18 @@ namespace libtorrent void torrent_handle::set_sequenced_download_threshold(int threshold) const { INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::set_sequenced_download_threshold, _1, threshold)); + 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); } std::string torrent_handle::name() const { INVARIANT_CHECK; - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::name, _1)); + + 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(); } @@ -358,40 +374,45 @@ namespace libtorrent { INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::piece_availability, _1, boost::ref(avail))); + 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); } void torrent_handle::piece_priority(int index, int priority) const { INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::set_piece_priority, _1, index, priority)); + 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); } int torrent_handle::piece_priority(int index) const { INVARIANT_CHECK; - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::piece_priority, _1, index)); + 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); } void torrent_handle::prioritize_pieces(std::vector const& pieces) const { INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::prioritize_pieces, _1, boost::cref(pieces))); + 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); } std::vector torrent_handle::piece_priorities() const { INVARIANT_CHECK; std::vector ret; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::piece_priorities, _1, boost::ref(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); return ret; } @@ -399,8 +420,9 @@ namespace libtorrent { INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::prioritize_files, _1, boost::cref(files))); + 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); } // ============ start deprecation =============== @@ -408,38 +430,43 @@ namespace libtorrent void torrent_handle::filter_piece(int index, bool filter) const { INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::filter_piece, _1, index, filter)); + 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); } void torrent_handle::filter_pieces(std::vector const& pieces) const { INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::filter_pieces, _1, boost::cref(pieces))); + 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); } bool torrent_handle::is_piece_filtered(int index) const { INVARIANT_CHECK; - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::is_piece_filtered, _1, index)); + 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); } std::vector torrent_handle::filtered_pieces() const { INVARIANT_CHECK; std::vector ret; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::filtered_pieces, _1, boost::ref(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); return ret; } void torrent_handle::filter_files(std::vector const& files) const { INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::filter_files, _1, files)); + 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); } // ============ end deprecation =============== @@ -449,32 +476,36 @@ namespace libtorrent { INVARIANT_CHECK; - return call_member const&>(m_ses - , m_chk, m_info_hash, bind(&torrent::trackers, _1)); + 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(); } void torrent_handle::add_url_seed(std::string const& url) const { INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::add_url_seed, _1, url)); + 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); } void torrent_handle::remove_url_seed(std::string const& url) const { INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::remove_url_seed, _1, url)); + 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); } std::set torrent_handle::url_seeds() const { INVARIANT_CHECK; - return call_member >(m_ses, m_chk, m_info_hash - , bind(&torrent::url_seeds, _1)); + 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(); } void torrent_handle::replace_trackers( @@ -482,17 +513,19 @@ namespace libtorrent { INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::replace_trackers, _1, urls)); + 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_info const& torrent_handle::get_torrent_info() const { INVARIANT_CHECK; - - if (!has_metadata()) throw_invalid_handle(); - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::torrent_file, _1)); + 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(); + return t->torrent_file(); } bool torrent_handle::is_valid() const @@ -641,8 +674,9 @@ namespace libtorrent { INVARIANT_CHECK; - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::save_path, _1)); + 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(); } void torrent_handle::connect_peer(tcp::endpoint const& adr, int source) const @@ -709,23 +743,26 @@ namespace libtorrent if (ratio < 1.f && ratio > 0.f) ratio = 1.f; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::set_ratio, _1, ratio)); + 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); } #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES void torrent_handle::resolve_countries(bool r) { INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::resolve_countries, _1, r)); + 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); } bool torrent_handle::resolve_countries() const { INVARIANT_CHECK; - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::resolving_countries, _1)); + 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(); } #endif diff --git a/libtorrent/src/torrent_info.cpp b/libtorrent/src/torrent_info.cpp index e43f3f297..d6dc27fa2 100755 --- a/libtorrent/src/torrent_info.cpp +++ b/libtorrent/src/torrent_info.cpp @@ -400,7 +400,9 @@ namespace libtorrent { if (i->first == "pieces" || i->first == "piece length" - || i->first == "length") + || i->first == "length" +// || i->first == "files" + || i->first == "name") continue; m_extra_info[i->first] = i->second; } @@ -824,8 +826,33 @@ namespace libtorrent m_nodes.push_back(node); } + 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.offset = offset; + fe.size = map[i].second; + offset += fe.size; + } + if (offset != total_size()) + { + m_remapped_files.clear(); + return false; + } + + return true; + } + std::vector torrent_info::map_block(int piece, size_type offset - , int size) const + , int size, bool storage) const { assert(num_files() > 0); std::vector ret; @@ -839,9 +866,9 @@ namespace libtorrent std::vector::const_iterator file_iter; int counter = 0; - for (file_iter = begin_files();; ++counter, ++file_iter) + for (file_iter = begin_files(storage);; ++counter, ++file_iter) { - assert(file_iter != end_files()); + assert(file_iter != end_files(storage)); if (file_offset < file_iter->size) { file_slice f; @@ -862,11 +889,11 @@ namespace libtorrent } peer_request torrent_info::map_file(int file_index, size_type file_offset - , int size) const + , int size, bool storage) const { - assert(file_index < (int)m_files.size()); + assert(file_index < num_files(storage)); assert(file_index >= 0); - size_type offset = file_offset + m_files[file_index].offset; + size_type offset = file_offset + file_at(file_index, storage).offset; peer_request ret; ret.piece = offset / piece_length();