Browse Source

more untested stuff: try to preserve piece_size when reading from disk.

first signature checking instead of hash.
miguelfreitas
miguel 11 years ago
parent
commit
6fb557e33c
  1. 8
      libtorrent/include/libtorrent/disk_io_thread.hpp
  2. 2
      libtorrent/include/libtorrent/torrent_info.hpp
  3. 79
      libtorrent/src/disk_io_thread.cpp
  4. 11
      libtorrent/src/session_impl.cpp
  5. 2
      libtorrent/src/storage.cpp
  6. 5
      libtorrent/src/torrent.cpp
  7. 3
      libtorrent/src/torrent_info.cpp

8
libtorrent/include/libtorrent/disk_io_thread.hpp

@ -322,6 +322,8 @@ namespace libtorrent
struct cached_piece_entry struct cached_piece_entry
{ {
int piece; int piece;
// read size
int piece_size;
// storage this piece belongs to // storage this piece belongs to
boost::intrusive_ptr<piece_manager> storage; boost::intrusive_ptr<piece_manager> storage;
// the pointers to the block data // the pointers to the block data
@ -373,7 +375,7 @@ namespace libtorrent
bool is_cache_hit(cached_piece_entry& p bool is_cache_hit(cached_piece_entry& p
, disk_io_job const& j, mutex::scoped_lock& l); , disk_io_job const& j, mutex::scoped_lock& l);
int copy_from_piece(cached_piece_entry& p, bool& hit 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 struct ignore_t
{ {
@ -409,8 +411,8 @@ namespace libtorrent
enum cache_flags_t { enum cache_flags_t {
cache_only = 1 cache_only = 1
}; };
int try_read_from_cache(disk_io_job const& j, bool& hit, int flags = 0); int try_read_from_cache(disk_io_job & j, bool& hit, int flags = 0);
int read_piece_from_cache_and_hash(disk_io_job const& j, sha1_hash& h); 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 int cache_piece(disk_io_job const& j, cache_piece_index_t::iterator& p
, bool& hit, int options, mutex::scoped_lock& l); , bool& hit, int options, mutex::scoped_lock& l);

2
libtorrent/include/libtorrent/torrent_info.hpp

@ -253,7 +253,7 @@ namespace libtorrent
#endif #endif
torrent_info(torrent_info const& t, int flags = 0); 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(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(char const* buffer, int size, error_code& ec, int flags = 0);
torrent_info(std::string const& filename, error_code& ec, int flags = 0); torrent_info(std::string const& filename, error_code& ec, int flags = 0);

79
libtorrent/src/disk_io_thread.cpp

@ -47,6 +47,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/time.hpp" #include "libtorrent/time.hpp"
#include "../../src/twister.h"
#if TORRENT_USE_MLOCK && !defined TORRENT_WINDOWS #if TORRENT_USE_MLOCK && !defined TORRENT_WINDOWS
#include <sys/mman.h> #include <sys/mman.h>
#endif #endif
@ -821,7 +823,7 @@ namespace libtorrent
return -1; return -1;
} }
if (ret != buffer_size) if (ret < 0)
{ {
// this means the file wasn't big enough for this read // this means the file wasn't big enough for this read
p.storage->get_storage_impl()->set_error("" p.storage->get_storage_impl()->set_error(""
@ -829,6 +831,7 @@ namespace libtorrent
free_piece(p, l); free_piece(p, l);
return -1; return -1;
} }
p.piece_size = ret;
int offset = 0; int offset = 0;
for (int i = 0; i < iov_counter; ++i) for (int i = 0; i < iov_counter; ++i)
@ -852,7 +855,7 @@ namespace libtorrent
return -1; return -1;
} }
if (ret != buffer_size) if (ret < 0)
{ {
// this means the file wasn't big enough for this read // this means the file wasn't big enough for this read
p.storage->get_storage_impl()->set_error("" p.storage->get_storage_impl()->set_error(""
@ -860,9 +863,10 @@ namespace libtorrent
free_piece(p, l); free_piece(p, l);
return -1; return -1;
} }
p.piece_size = ret;
} }
TORRENT_ASSERT(ret == buffer_size); TORRENT_ASSERT(ret <= buffer_size);
return ret; return ret;
} }
@ -1049,7 +1053,7 @@ namespace libtorrent
} }
// cache the entire piece and hash it // 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); TORRENT_ASSERT(j.buffer);
@ -1069,21 +1073,33 @@ namespace libtorrent
bool hit; bool hit;
int ret = cache_piece(j, p, hit, ignore_cache_size, l); int ret = cache_piece(j, p, hit, ignore_cache_size, l);
if (ret < 0) return ret; if (ret < 0) return ret;
piece_size = p->piece_size;
if (!m_settings.disable_hash_checks) if (!m_settings.disable_hash_checks)
{ {
hasher ctx; *hash_ok = false;
for (int i = 0; i < blocks_in_piece; ++i) lazy_entry v;
{ int pos;
TORRENT_ASSERT(p->blocks[i].buf); error_code ec;
ctx.update((char const*)p->blocks[i].buf, (std::min)(piece_size, m_block_size)); if (lazy_bdecode((char const*)p->blocks[0].buf, (char const*)p->blocks[0].buf
piece_size -= m_block_size; + piece_size, v, ec, &pos) == 0) {
}
h = ctx.final(); 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<char const*, int> postbuf = post->data_section();
*hash_ok = verifySignature(
std::string(postbuf.first,postbuf.second),
username, sig);
}
}
}
} }
ret = copy_from_piece(const_cast<cached_piece_entry&>(*p), hit, j, l); ret = copy_from_piece(const_cast<cached_piece_entry&>(*p), hit, j, l);
TORRENT_ASSERT(ret > 0); TORRENT_ASSERT(ret > 0);
if (ret < 0) return ret; if (ret < 0) return ret;
cache_piece_index_t& idx = m_read_pieces.get<0>(); 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 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); TORRENT_ASSERT(j.buffer);
@ -1196,10 +1212,18 @@ namespace libtorrent
int ret = read_into_piece(p, block, 0, blocks_to_read, l); int ret = read_into_piece(p, block, 0, blocks_to_read, l);
hit = false; hit = false;
if (ret < 0) return ret; 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); 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 // build a vector of all the buffers we need to free
// and free them all in one go // and free them all in one go
std::vector<char*> buffers; std::vector<char*> buffers;
@ -1233,10 +1257,10 @@ namespace libtorrent
++block; ++block;
} }
if (!buffers.empty()) free_multiple_buffers(&buffers[0], buffers.size()); 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.buffer);
TORRENT_ASSERT(j.cache_min_time >= 0); TORRENT_ASSERT(j.cache_min_time >= 0);
@ -1276,7 +1300,7 @@ namespace libtorrent
TORRENT_ASSERT(p != idx.end()); TORRENT_ASSERT(p != idx.end());
ret = copy_from_piece(const_cast<cached_piece_entry&>(*p), hit, j, l); ret = copy_from_piece(const_cast<cached_piece_entry&>(*p), hit, j, l);
if (ret < 0) return ret; if (ret < 0) return ret;
if (p->num_blocks == 0) idx.erase(p); if (p->num_blocks == 0) idx.erase(p);
else idx.modify(p, update_last_use(j.cache_min_time)); 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 // since we need to check the hash, this function
// will ignore the cache size limit (at least for // will ignore the cache size limit (at least for
// reading and hashing, not for keeping it around) // reading and hashing, not for keeping it around)
sha1_hash h; bool hash_ok;
ret = read_piece_from_cache_and_hash(j, h); ret = read_piece_from_cache_and_hash(j, &hash_ok);
// -2 means there's no space in the read cache // -2 means there's no space in the read cache
// or that the read cache is disabled // or that the read cache is disabled
@ -1948,7 +1972,7 @@ namespace libtorrent
break; break;
} }
if (!m_settings.disable_hash_checks) 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) if (ret == -3)
{ {
j.storage->mark_failed(j.piece); j.storage->mark_failed(j.piece);
@ -2026,7 +2050,9 @@ namespace libtorrent
test_error(j); test_error(j);
break; 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 // this means the file wasn't big enough for this read
j.buffer = 0; j.buffer = 0;
@ -2035,7 +2061,8 @@ namespace libtorrent
j.str.clear(); j.str.clear();
ret = -1; ret = -1;
break; break;
} }
++m_cache_stats.blocks_read; ++m_cache_stats.blocks_read;
hit = false; hit = false;
} }

11
libtorrent/src/session_impl.cpp

@ -5115,7 +5115,7 @@ retry:
if (lazy_bdecode(&params.resume_data[0], &params.resume_data[0] if (lazy_bdecode(&params.resume_data[0], &params.resume_data[0]
+ params.resume_data.size(), tmp, ec, &pos) == 0 + params.resume_data.size(), tmp, ec, &pos) == 0
&& tmp.type() == lazy_entry::dict_t && 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 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
session_log("found metadata in resume data"); 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 // verify the info-hash of the metadata stored in the resume file matches
// the torrent we're loading // the torrent we're loading
/* [MF]
std::pair<char const*, int> buf = info->data_section(); std::pair<char const*, int> buf = info->data_section();
sha1_hash resume_ih = hasher(buf.first, buf.second).final(); 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 // 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 // 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 #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
session_log("info-hash matched"); session_log("info-hash matched");
#endif #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 (params.ti->parse_info_section(*info, ec, 0))
{ {
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
@ -5154,6 +5158,7 @@ retry:
, ec.message().c_str()); , ec.message().c_str());
#endif #endif
} }
*/
} }
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
else else

2
libtorrent/src/storage.cpp

@ -2511,11 +2511,13 @@ ret:
TORRENT_ASSERT(have_piece == -1); TORRENT_ASSERT(have_piece == -1);
// initialization for the full check // initialization for the full check
/* [MF]
if (m_hash_to_piece.empty()) if (m_hash_to_piece.empty())
{ {
for (int i = 0; i < m_files.num_pieces(); ++i) for (int i = 0; i < m_files.num_pieces(); ++i)
m_hash_to_piece.insert(std::pair<const sha1_hash, int>(m_info->hash_for_piece(i), i)); m_hash_to_piece.insert(std::pair<const sha1_hash, int>(m_info->hash_for_piece(i), i));
} }
*/
partial_hash ph; partial_hash ph;
int num_read = 0; int num_read = 0;

5
libtorrent/src/torrent.cpp

@ -458,7 +458,7 @@ namespace libtorrent
} }
if (!m_torrent_file) 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(); m_trackers = m_torrent_file->trackers();
if (m_torrent_file->is_valid()) if (m_torrent_file->is_valid())
@ -5148,12 +5148,13 @@ namespace libtorrent
const sha1_hash& info_hash = torrent_file().info_hash(); const sha1_hash& info_hash = torrent_file().info_hash();
ret["info-hash"] = std::string((char*)info_hash.begin(), (char*)info_hash.end()); ret["info-hash"] = std::string((char*)info_hash.begin(), (char*)info_hash.end());
/* [MF] don't save metadata
if (valid_metadata()) if (valid_metadata())
{ {
if (m_magnet_link || (m_save_resume_flags & torrent_handle::save_info_dict)) if (m_magnet_link || (m_save_resume_flags & torrent_handle::save_info_dict))
ret["info"] = bdecode(&torrent_file().metadata()[0] ret["info"] = bdecode(&torrent_file().metadata()[0]
, &torrent_file().metadata()[0] + torrent_file().metadata_size()); , &torrent_file().metadata()[0] + torrent_file().metadata_size());
} } */
// blocks per piece // blocks per piece
int num_blocks_per_piece = int num_blocks_per_piece =

3
libtorrent/src/torrent_info.cpp

@ -829,7 +829,7 @@ namespace libtorrent
// will not contain any hashes, comments, creation date // will not contain any hashes, comments, creation date
// just the necessary to use it with piece manager // just the necessary to use it with piece manager
// used for torrents with no metadata // 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_merkle_first_leaf(0)
, m_piece_hashes(0) , m_piece_hashes(0)
, m_creation_date(time(0)) , m_creation_date(time(0))
@ -845,6 +845,7 @@ namespace libtorrent
file_entry e; file_entry e;
e.size = 1; e.size = 1;
m_files.add_file(e); m_files.add_file(e);
m_files.set_name(name);
} }
torrent_info::~torrent_info() torrent_info::~torrent_info()

Loading…
Cancel
Save