From 6fb557e33c68c7d09a96d70ed59c216fedf4c6f8 Mon Sep 17 00:00:00 2001 From: miguel Date: Sun, 18 Aug 2013 09:53:35 -0300 Subject: [PATCH] more untested stuff: try to preserve piece_size when reading from disk. first signature checking instead of hash. --- .../include/libtorrent/disk_io_thread.hpp | 8 +- .../include/libtorrent/torrent_info.hpp | 2 +- libtorrent/src/disk_io_thread.cpp | 81 ++++++++++++------- libtorrent/src/session_impl.cpp | 11 ++- libtorrent/src/storage.cpp | 2 + libtorrent/src/torrent.cpp | 5 +- libtorrent/src/torrent_info.cpp | 3 +- 7 files changed, 75 insertions(+), 37 deletions(-) diff --git a/libtorrent/include/libtorrent/disk_io_thread.hpp b/libtorrent/include/libtorrent/disk_io_thread.hpp index 4d172eb2..ab862b38 100644 --- a/libtorrent/include/libtorrent/disk_io_thread.hpp +++ b/libtorrent/include/libtorrent/disk_io_thread.hpp @@ -322,6 +322,8 @@ namespace libtorrent struct cached_piece_entry { int piece; + // read size + int piece_size; // storage this piece belongs to boost::intrusive_ptr storage; // the pointers to the block data @@ -373,7 +375,7 @@ namespace libtorrent bool is_cache_hit(cached_piece_entry& p , disk_io_job const& j, mutex::scoped_lock& l); int copy_from_piece(cached_piece_entry& p, bool& hit - , disk_io_job const& j, mutex::scoped_lock& l); + , disk_io_job & j, mutex::scoped_lock& l); struct ignore_t { @@ -409,8 +411,8 @@ namespace libtorrent enum cache_flags_t { cache_only = 1 }; - int try_read_from_cache(disk_io_job const& j, bool& hit, int flags = 0); - int read_piece_from_cache_and_hash(disk_io_job const& j, sha1_hash& h); + int try_read_from_cache(disk_io_job & j, bool& hit, int flags = 0); + int read_piece_from_cache_and_hash(disk_io_job & j, bool *hash_ok); int cache_piece(disk_io_job const& j, cache_piece_index_t::iterator& p , bool& hit, int options, mutex::scoped_lock& l); diff --git a/libtorrent/include/libtorrent/torrent_info.hpp b/libtorrent/include/libtorrent/torrent_info.hpp index 17f01885..f7225d24 100644 --- a/libtorrent/include/libtorrent/torrent_info.hpp +++ b/libtorrent/include/libtorrent/torrent_info.hpp @@ -253,7 +253,7 @@ namespace libtorrent #endif torrent_info(torrent_info const& t, int flags = 0); - torrent_info(sha1_hash const& info_hash, int flags = 0); + torrent_info(sha1_hash const& info_hash, std::string const name, int flags = 0); torrent_info(lazy_entry const& torrent_file, error_code& ec, int flags = 0); torrent_info(char const* buffer, int size, error_code& ec, int flags = 0); torrent_info(std::string const& filename, error_code& ec, int flags = 0); diff --git a/libtorrent/src/disk_io_thread.cpp b/libtorrent/src/disk_io_thread.cpp index 7da6cb78..ccb9b1ac 100644 --- a/libtorrent/src/disk_io_thread.cpp +++ b/libtorrent/src/disk_io_thread.cpp @@ -47,6 +47,8 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/time.hpp" +#include "../../src/twister.h" + #if TORRENT_USE_MLOCK && !defined TORRENT_WINDOWS #include #endif @@ -821,7 +823,7 @@ namespace libtorrent return -1; } - if (ret != buffer_size) + if (ret < 0) { // this means the file wasn't big enough for this read p.storage->get_storage_impl()->set_error("" @@ -829,7 +831,8 @@ namespace libtorrent free_piece(p, l); return -1; } - + p.piece_size = ret; + int offset = 0; for (int i = 0; i < iov_counter; ++i) { @@ -852,7 +855,7 @@ namespace libtorrent return -1; } - if (ret != buffer_size) + if (ret < 0) { // this means the file wasn't big enough for this read p.storage->get_storage_impl()->set_error("" @@ -860,9 +863,10 @@ namespace libtorrent free_piece(p, l); return -1; } + p.piece_size = ret; } - TORRENT_ASSERT(ret == buffer_size); + TORRENT_ASSERT(ret <= buffer_size); return ret; } @@ -1049,7 +1053,7 @@ namespace libtorrent } // cache the entire piece and hash it - int disk_io_thread::read_piece_from_cache_and_hash(disk_io_job const& j, sha1_hash& h) + int disk_io_thread::read_piece_from_cache_and_hash(disk_io_job & j, bool *hash_ok) { TORRENT_ASSERT(j.buffer); @@ -1069,21 +1073,33 @@ namespace libtorrent bool hit; int ret = cache_piece(j, p, hit, ignore_cache_size, l); if (ret < 0) return ret; + piece_size = p->piece_size; if (!m_settings.disable_hash_checks) - { - hasher ctx; - - for (int i = 0; i < blocks_in_piece; ++i) - { - TORRENT_ASSERT(p->blocks[i].buf); - ctx.update((char const*)p->blocks[i].buf, (std::min)(piece_size, m_block_size)); - piece_size -= m_block_size; - } - h = ctx.final(); + { + *hash_ok = false; + + lazy_entry v; + int pos; + error_code ec; + if (lazy_bdecode((char const*)p->blocks[0].buf, (char const*)p->blocks[0].buf + + piece_size, v, ec, &pos) == 0) { + + if( v.type() == lazy_entry::dict_t ) { + lazy_entry const* post = v.dict_find("userpost"); + std::string sig = v.dict_find_string_value("sig_userpost"); + std::string username = j.storage->info()->name(); + if( post && sig.size() ) { + std::pair postbuf = post->data_section(); + *hash_ok = verifySignature( + std::string(postbuf.first,postbuf.second), + username, sig); + } + } + } } - ret = copy_from_piece(const_cast(*p), hit, j, l); + ret = copy_from_piece(const_cast(*p), hit, j, l); TORRENT_ASSERT(ret > 0); if (ret < 0) return ret; cache_piece_index_t& idx = m_read_pieces.get<0>(); @@ -1146,7 +1162,7 @@ namespace libtorrent } int disk_io_thread::copy_from_piece(cached_piece_entry& p, bool& hit - , disk_io_job const& j, mutex::scoped_lock& l) + , disk_io_job & j, mutex::scoped_lock& l) { TORRENT_ASSERT(j.buffer); @@ -1196,10 +1212,18 @@ namespace libtorrent int ret = read_into_piece(p, block, 0, blocks_to_read, l); hit = false; if (ret < 0) return ret; - if (ret < size + block_offset) return -2; + //[MF] + TORRENT_ASSERT(ret == p.piece_size); + piece_size = ret; + //if (ret < size + block_offset) return -2; TORRENT_ASSERT(p.blocks[block].buf); } + //[MF] + TORRENT_ASSERT(j.buffer_size >= piece_size); + j.buffer_size = piece_size; + size = piece_size; + // build a vector of all the buffers we need to free // and free them all in one go std::vector buffers; @@ -1233,10 +1257,10 @@ namespace libtorrent ++block; } if (!buffers.empty()) free_multiple_buffers(&buffers[0], buffers.size()); - return j.buffer_size; - } + return j.buffer_size; + } - int disk_io_thread::try_read_from_cache(disk_io_job const& j, bool& hit, int flags) + int disk_io_thread::try_read_from_cache(disk_io_job & j, bool& hit, int flags) { TORRENT_ASSERT(j.buffer); TORRENT_ASSERT(j.cache_min_time >= 0); @@ -1276,7 +1300,7 @@ namespace libtorrent TORRENT_ASSERT(p != idx.end()); - ret = copy_from_piece(const_cast(*p), hit, j, l); + ret = copy_from_piece(const_cast(*p), hit, j, l); if (ret < 0) return ret; if (p->num_blocks == 0) idx.erase(p); else idx.modify(p, update_last_use(j.cache_min_time)); @@ -1937,8 +1961,8 @@ namespace libtorrent // since we need to check the hash, this function // will ignore the cache size limit (at least for // reading and hashing, not for keeping it around) - sha1_hash h; - ret = read_piece_from_cache_and_hash(j, h); + bool hash_ok; + ret = read_piece_from_cache_and_hash(j, &hash_ok); // -2 means there's no space in the read cache // or that the read cache is disabled @@ -1948,7 +1972,7 @@ namespace libtorrent break; } if (!m_settings.disable_hash_checks) - ret = (j.storage->info()->hash_for_piece(j.piece) == h)?ret:-3; + ret = (hash_ok)?ret:-3; if (ret == -3) { j.storage->mark_failed(j.piece); @@ -2026,7 +2050,9 @@ namespace libtorrent test_error(j); break; } - if (ret != j.buffer_size) + //[MF] size is unknown beforehand + j.buffer_size = ret; + if (ret == 0) { // this means the file wasn't big enough for this read j.buffer = 0; @@ -2035,7 +2061,8 @@ namespace libtorrent j.str.clear(); ret = -1; break; - } + } + ++m_cache_stats.blocks_read; hit = false; } diff --git a/libtorrent/src/session_impl.cpp b/libtorrent/src/session_impl.cpp index d9e6963f..736d7419 100644 --- a/libtorrent/src/session_impl.cpp +++ b/libtorrent/src/session_impl.cpp @@ -5115,7 +5115,7 @@ retry: if (lazy_bdecode(¶ms.resume_data[0], ¶ms.resume_data[0] + params.resume_data.size(), tmp, ec, &pos) == 0 && tmp.type() == lazy_entry::dict_t - && (info = tmp.dict_find_dict("info"))) + /* && (info = tmp.dict_find_dict("info")) */) { #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING session_log("found metadata in resume data"); @@ -5123,8 +5123,12 @@ retry: // verify the info-hash of the metadata stored in the resume file matches // the torrent we're loading + /* [MF] std::pair buf = info->data_section(); sha1_hash resume_ih = hasher(buf.first, buf.second).final(); + */ + std::string info_hash = tmp.dict_find_string_value("info-hash"); + sha1_hash resume_ih = sha1_hash(info_hash); // if url is set, the info_hash is not actually the info-hash of the // torrent, but the hash of the URL, until we have the full torrent @@ -5136,8 +5140,8 @@ retry: #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING session_log("info-hash matched"); #endif - params.ti = new torrent_info(resume_ih); - + params.ti = new torrent_info(resume_ih, params.name); + /* if (params.ti->parse_info_section(*info, ec, 0)) { #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING @@ -5154,6 +5158,7 @@ retry: , ec.message().c_str()); #endif } + */ } #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING else diff --git a/libtorrent/src/storage.cpp b/libtorrent/src/storage.cpp index d8067370..7358234d 100644 --- a/libtorrent/src/storage.cpp +++ b/libtorrent/src/storage.cpp @@ -2511,11 +2511,13 @@ ret: TORRENT_ASSERT(have_piece == -1); // initialization for the full check + /* [MF] if (m_hash_to_piece.empty()) { for (int i = 0; i < m_files.num_pieces(); ++i) m_hash_to_piece.insert(std::pair(m_info->hash_for_piece(i), i)); } + */ partial_hash ph; int num_read = 0; diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index 20c67acd..b8840589 100644 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -458,7 +458,7 @@ namespace libtorrent } if (!m_torrent_file) - m_torrent_file = (p.ti ? p.ti : new torrent_info(info_hash)); + m_torrent_file = (p.ti ? p.ti : new torrent_info(info_hash, p.name)); m_trackers = m_torrent_file->trackers(); if (m_torrent_file->is_valid()) @@ -5148,12 +5148,13 @@ namespace libtorrent const sha1_hash& info_hash = torrent_file().info_hash(); ret["info-hash"] = std::string((char*)info_hash.begin(), (char*)info_hash.end()); + /* [MF] don't save metadata if (valid_metadata()) { if (m_magnet_link || (m_save_resume_flags & torrent_handle::save_info_dict)) ret["info"] = bdecode(&torrent_file().metadata()[0] , &torrent_file().metadata()[0] + torrent_file().metadata_size()); - } + } */ // blocks per piece int num_blocks_per_piece = diff --git a/libtorrent/src/torrent_info.cpp b/libtorrent/src/torrent_info.cpp index 78a76551..3d7137c9 100644 --- a/libtorrent/src/torrent_info.cpp +++ b/libtorrent/src/torrent_info.cpp @@ -829,7 +829,7 @@ namespace libtorrent // will not contain any hashes, comments, creation date // just the necessary to use it with piece manager // used for torrents with no metadata - torrent_info::torrent_info(sha1_hash const& info_hash, int flags) + torrent_info::torrent_info(sha1_hash const& info_hash, std::string const name, int flags) : m_merkle_first_leaf(0) , m_piece_hashes(0) , m_creation_date(time(0)) @@ -845,6 +845,7 @@ namespace libtorrent file_entry e; e.size = 1; m_files.add_file(e); + m_files.set_name(name); } torrent_info::~torrent_info()