added support for torrents with odd piece sizes

This commit is contained in:
Arvid Norberg 2010-02-23 16:26:24 +00:00
parent 5c5f1d23a9
commit eff49e42a7
9 changed files with 28 additions and 52 deletions

View File

@ -106,7 +106,7 @@
* improved LSD performance and made the interval configurable
* improved UDP tracker support by caching connect tokens
* fast piece optimization
* fixed error handling with torrents with invalid piece sizes
* added support for torrents with odd piece sizes
* fixed issue with disk read cache not being cleared when removing torrents
release 0.14.9

View File

@ -6275,8 +6275,7 @@ code symbol description
------ ----------------------------------------- -----------------------------------------------------------------
81 packet_too_large The packet size exceeded the upper sanity check-limit
------ ----------------------------------------- -----------------------------------------------------------------
82 torrent_invalid_piece_size The .torrent file has an invalid piece size. It needs to be an
even 16 kiB multiple
82 reserved
------ ----------------------------------------- -----------------------------------------------------------------
83 http_error The web server responded with an error
------ ----------------------------------------- -----------------------------------------------------------------

View File

@ -139,7 +139,7 @@ namespace libtorrent
duplicate_peer_id,
torrent_removed,
packet_too_large,
torrent_invalid_piece_size,
reserved,
http_error,
missing_location,
invalid_redirection,

View File

@ -192,7 +192,7 @@ namespace libtorrent
int sparse_regions() const { return m_sparse_regions; }
// sets all pieces to dont-have
void init(int blocks_per_piece, int total_num_blocks);
void init(int blocks_per_piece, int blocks_in_last_piece, int total_num_pieces);
int num_pieces() const { return int(m_piece_map.size()); }
bool have_piece(int index) const

View File

@ -559,7 +559,7 @@ namespace libtorrent
}
int block_size() const { TORRENT_ASSERT(m_block_size_shift > 0); return 1 << m_block_size_shift; }
peer_request to_req(piece_block const& p);
peer_request to_req(piece_block const& p) const;
void disconnect_all(error_code const& ec);
int disconnect_peers(int num);

View File

@ -130,7 +130,7 @@ namespace libtorrent
"duplicate peer-id",
"torrent removed",
"packet too large",
"invalid piece size in torrent file",
"",
"HTTP error",
"missing location header",
"invalid redirection",

View File

@ -1037,19 +1037,10 @@ namespace libtorrent
torrent_info const& ti = t->torrent_file();
return p.piece >= 0
&& p.piece < t->torrent_file().num_pieces()
&& p.length >= 0
&& p.piece < ti.num_pieces()
&& p.start >= 0
&& (p.length == t->block_size()
|| (p.length < t->block_size()
&& p.piece == ti.num_pieces()-1
&& p.start + p.length == ti.piece_size(p.piece))
|| (m_request_large_blocks
&& p.length <= ti.piece_length() * (m_prefer_whole_pieces == 0 ?
1 : m_prefer_whole_pieces)))
&& p.piece * size_type(ti.piece_length()) + p.start + p.length
<= ti.total_size()
&& (p.start % t->block_size() == 0);
&& p.start < ti.piece_length()
&& t->to_req(piece_block(p.piece, p.start / t->block_size())) == p;
}
void peer_connection::attach_to_torrent(sha1_hash const& ih)
@ -2088,7 +2079,7 @@ namespace libtorrent
if (!t->is_seed())
{
const int blocks_per_piece = static_cast<int>(
t->torrent_file().piece_length() / t->block_size());
(t->torrent_file().piece_length() + t->block_size() - 1) / t->block_size());
std::vector<piece_picker::downloading_piece> const& dl_queue
= t->picker().get_download_queue();
@ -2216,9 +2207,7 @@ namespace libtorrent
std::vector<piece_block> finished_blocks;
piece_block block_finished(p.piece, p.start / t->block_size());
TORRENT_ASSERT(p.start % t->block_size() == 0);
TORRENT_ASSERT(p.length == t->block_size()
|| p.length == t->torrent_file().total_size() % t->block_size());
TORRENT_ASSERT(verify_piece(p));
std::vector<pending_block>::iterator b
= std::find_if(
@ -4967,13 +4956,9 @@ namespace libtorrent
in_download_queue = true;
outstanding_bytes += p->full_block_bytes - m_received_in_piece;
}
else if (i->block == last_block)
{
outstanding_bytes += last_block_size;
}
else
{
outstanding_bytes += block_size;
outstanding_bytes += t->to_req(i->block).length;
}
}
//if (p && p->bytes_downloaded < p->full_block_bytes) TORRENT_ASSERT(in_download_queue);

View File

@ -76,18 +76,17 @@ namespace libtorrent
#endif
}
void piece_picker::init(int blocks_per_piece, int total_num_blocks)
void piece_picker::init(int blocks_per_piece, int blocks_in_last_piece, int total_num_pieces)
{
TORRENT_ASSERT(blocks_per_piece > 0);
TORRENT_ASSERT(total_num_blocks >= 0);
TORRENT_ASSERT(total_num_pieces > 0);
#ifdef TORRENT_PICKER_LOG
std::cerr << "piece_picker::init()" << std::endl;
#endif
// allocate the piece_map to cover all pieces
// and make them invalid (as if we don't have a single piece)
m_piece_map.resize((total_num_blocks + blocks_per_piece-1) / blocks_per_piece
, piece_pos(0, 0));
m_piece_map.resize(total_num_pieces, piece_pos(0, 0));
m_reverse_cursor = int(m_piece_map.size());
m_cursor = 0;
@ -118,7 +117,7 @@ namespace libtorrent
TORRENT_ASSERT(m_piece_map.size() < piece_pos::we_have_index);
m_blocks_per_piece = blocks_per_piece;
m_blocks_in_last_piece = total_num_blocks % blocks_per_piece;
m_blocks_in_last_piece = blocks_in_last_piece;
if (m_blocks_in_last_piece == 0) m_blocks_in_last_piece = blocks_per_piece;
TORRENT_ASSERT(m_blocks_in_last_piece <= m_blocks_per_piece);

View File

@ -744,7 +744,7 @@ namespace libtorrent
return m_torrent_file->add_merkle_nodes(nodes, piece);
}
peer_request torrent::to_req(piece_block const& p)
peer_request torrent::to_req(piece_block const& p) const
{
int block_offset = p.block_index * block_size();
int block = (std::min)(torrent_file().piece_size(
@ -817,14 +817,6 @@ namespace libtorrent
return;
}
if (m_torrent_file->piece_length() % block_size() != 0)
{
// TODO: try to adjust the block size
set_error(errors::torrent_invalid_piece_size, "");
pause();
return;
}
// the shared_from_this() will create an intentional
// cycle of ownership, se the hpp file for description.
m_owning_storage = new piece_manager(shared_from_this(), m_torrent_file
@ -834,8 +826,10 @@ namespace libtorrent
if (has_picker())
{
m_picker->init((std::max)(m_torrent_file->piece_length() / block_size(), 1)
, int((m_torrent_file->total_size()+block_size()-1) / block_size()));
int blocks_per_piece = (m_torrent_file->piece_length() + block_size() - 1) / block_size();
int blocks_in_last_piece = ((m_torrent_file->total_size() % m_torrent_file->piece_length())
+ block_size() - 1) / block_size();
m_picker->init(blocks_per_piece, blocks_in_last_piece, m_torrent_file->num_pieces());
}
std::vector<std::string> const& url_seeds = m_torrent_file->url_seeds();
@ -1153,8 +1147,11 @@ namespace libtorrent
m_owning_storage->async_release_files();
if (!m_picker) m_picker.reset(new piece_picker());
std::fill(m_file_progress.begin(), m_file_progress.end(), 0);
m_picker->init(m_torrent_file->piece_length() / block_size()
, int((m_torrent_file->total_size() + block_size()-1)/block_size()));
int blocks_per_piece = (m_torrent_file->piece_length() + block_size() - 1) / block_size();
int blocks_in_last_piece = ((m_torrent_file->total_size() % m_torrent_file->piece_length())
+ block_size() - 1) / block_size();
m_picker->init(blocks_per_piece, blocks_in_last_piece, m_torrent_file->num_pieces());
// assume that we don't have anything
TORRENT_ASSERT(m_picker->num_have() == 0);
m_files_checked = false;
@ -1972,11 +1969,8 @@ namespace libtorrent
}
#ifdef TORRENT_DEBUG
TORRENT_ASSERT(p->bytes_downloaded <= p->full_block_bytes);
if (p->piece_index == last_piece_index
&& p->block_index == m_torrent_file->piece_size(last_piece) / block_size())
TORRENT_ASSERT(p->full_block_bytes == m_torrent_file->piece_size(last_piece) % block_size());
else
TORRENT_ASSERT(p->full_block_bytes == block_size());
TORRENT_ASSERT(p->full_block_bytes == to_req(piece_block(
p->piece_index, p->block_index)).length);
#endif
}
for (std::map<piece_block, int>::iterator i = downloading_piece.begin();
@ -4856,7 +4850,6 @@ namespace libtorrent
if (m_files_checked && valid_metadata())
{
TORRENT_ASSERT(block_size() > 0);
TORRENT_ASSERT((m_torrent_file->piece_length() & (block_size()-1)) == 0);
}
// if (is_seed()) TORRENT_ASSERT(m_picker.get() == 0);