added support for torrents with odd piece sizes
This commit is contained in:
parent
5c5f1d23a9
commit
eff49e42a7
|
@ -106,7 +106,7 @@
|
||||||
* improved LSD performance and made the interval configurable
|
* improved LSD performance and made the interval configurable
|
||||||
* improved UDP tracker support by caching connect tokens
|
* improved UDP tracker support by caching connect tokens
|
||||||
* fast piece optimization
|
* 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
|
* fixed issue with disk read cache not being cleared when removing torrents
|
||||||
|
|
||||||
release 0.14.9
|
release 0.14.9
|
||||||
|
|
|
@ -6275,8 +6275,7 @@ code symbol description
|
||||||
------ ----------------------------------------- -----------------------------------------------------------------
|
------ ----------------------------------------- -----------------------------------------------------------------
|
||||||
81 packet_too_large The packet size exceeded the upper sanity check-limit
|
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
|
82 reserved
|
||||||
even 16 kiB multiple
|
|
||||||
------ ----------------------------------------- -----------------------------------------------------------------
|
------ ----------------------------------------- -----------------------------------------------------------------
|
||||||
83 http_error The web server responded with an error
|
83 http_error The web server responded with an error
|
||||||
------ ----------------------------------------- -----------------------------------------------------------------
|
------ ----------------------------------------- -----------------------------------------------------------------
|
||||||
|
|
|
@ -139,7 +139,7 @@ namespace libtorrent
|
||||||
duplicate_peer_id,
|
duplicate_peer_id,
|
||||||
torrent_removed,
|
torrent_removed,
|
||||||
packet_too_large,
|
packet_too_large,
|
||||||
torrent_invalid_piece_size,
|
reserved,
|
||||||
http_error,
|
http_error,
|
||||||
missing_location,
|
missing_location,
|
||||||
invalid_redirection,
|
invalid_redirection,
|
||||||
|
|
|
@ -192,7 +192,7 @@ namespace libtorrent
|
||||||
int sparse_regions() const { return m_sparse_regions; }
|
int sparse_regions() const { return m_sparse_regions; }
|
||||||
|
|
||||||
// sets all pieces to dont-have
|
// 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()); }
|
int num_pieces() const { return int(m_piece_map.size()); }
|
||||||
|
|
||||||
bool have_piece(int index) const
|
bool have_piece(int index) const
|
||||||
|
|
|
@ -559,7 +559,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
int block_size() const { TORRENT_ASSERT(m_block_size_shift > 0); return 1 << m_block_size_shift; }
|
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);
|
void disconnect_all(error_code const& ec);
|
||||||
int disconnect_peers(int num);
|
int disconnect_peers(int num);
|
||||||
|
|
|
@ -130,7 +130,7 @@ namespace libtorrent
|
||||||
"duplicate peer-id",
|
"duplicate peer-id",
|
||||||
"torrent removed",
|
"torrent removed",
|
||||||
"packet too large",
|
"packet too large",
|
||||||
"invalid piece size in torrent file",
|
"",
|
||||||
"HTTP error",
|
"HTTP error",
|
||||||
"missing location header",
|
"missing location header",
|
||||||
"invalid redirection",
|
"invalid redirection",
|
||||||
|
|
|
@ -1037,19 +1037,10 @@ namespace libtorrent
|
||||||
torrent_info const& ti = t->torrent_file();
|
torrent_info const& ti = t->torrent_file();
|
||||||
|
|
||||||
return p.piece >= 0
|
return p.piece >= 0
|
||||||
&& p.piece < t->torrent_file().num_pieces()
|
&& p.piece < ti.num_pieces()
|
||||||
&& p.length >= 0
|
|
||||||
&& p.start >= 0
|
&& p.start >= 0
|
||||||
&& (p.length == t->block_size()
|
&& p.start < ti.piece_length()
|
||||||
|| (p.length < t->block_size()
|
&& t->to_req(piece_block(p.piece, p.start / t->block_size())) == p;
|
||||||
&& 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void peer_connection::attach_to_torrent(sha1_hash const& ih)
|
void peer_connection::attach_to_torrent(sha1_hash const& ih)
|
||||||
|
@ -2088,7 +2079,7 @@ namespace libtorrent
|
||||||
if (!t->is_seed())
|
if (!t->is_seed())
|
||||||
{
|
{
|
||||||
const int blocks_per_piece = static_cast<int>(
|
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
|
std::vector<piece_picker::downloading_piece> const& dl_queue
|
||||||
= t->picker().get_download_queue();
|
= t->picker().get_download_queue();
|
||||||
|
@ -2216,9 +2207,7 @@ namespace libtorrent
|
||||||
|
|
||||||
std::vector<piece_block> finished_blocks;
|
std::vector<piece_block> finished_blocks;
|
||||||
piece_block block_finished(p.piece, p.start / t->block_size());
|
piece_block block_finished(p.piece, p.start / t->block_size());
|
||||||
TORRENT_ASSERT(p.start % t->block_size() == 0);
|
TORRENT_ASSERT(verify_piece(p));
|
||||||
TORRENT_ASSERT(p.length == t->block_size()
|
|
||||||
|| p.length == t->torrent_file().total_size() % t->block_size());
|
|
||||||
|
|
||||||
std::vector<pending_block>::iterator b
|
std::vector<pending_block>::iterator b
|
||||||
= std::find_if(
|
= std::find_if(
|
||||||
|
@ -4967,13 +4956,9 @@ namespace libtorrent
|
||||||
in_download_queue = true;
|
in_download_queue = true;
|
||||||
outstanding_bytes += p->full_block_bytes - m_received_in_piece;
|
outstanding_bytes += p->full_block_bytes - m_received_in_piece;
|
||||||
}
|
}
|
||||||
else if (i->block == last_block)
|
|
||||||
{
|
|
||||||
outstanding_bytes += last_block_size;
|
|
||||||
}
|
|
||||||
else
|
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);
|
//if (p && p->bytes_downloaded < p->full_block_bytes) TORRENT_ASSERT(in_download_queue);
|
||||||
|
|
|
@ -76,18 +76,17 @@ namespace libtorrent
|
||||||
#endif
|
#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(blocks_per_piece > 0);
|
||||||
TORRENT_ASSERT(total_num_blocks >= 0);
|
TORRENT_ASSERT(total_num_pieces > 0);
|
||||||
|
|
||||||
#ifdef TORRENT_PICKER_LOG
|
#ifdef TORRENT_PICKER_LOG
|
||||||
std::cerr << "piece_picker::init()" << std::endl;
|
std::cerr << "piece_picker::init()" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
// allocate the piece_map to cover all pieces
|
// allocate the piece_map to cover all pieces
|
||||||
// and make them invalid (as if we don't have a single piece)
|
// 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
|
m_piece_map.resize(total_num_pieces, piece_pos(0, 0));
|
||||||
, piece_pos(0, 0));
|
|
||||||
m_reverse_cursor = int(m_piece_map.size());
|
m_reverse_cursor = int(m_piece_map.size());
|
||||||
m_cursor = 0;
|
m_cursor = 0;
|
||||||
|
|
||||||
|
@ -118,7 +117,7 @@ namespace libtorrent
|
||||||
TORRENT_ASSERT(m_piece_map.size() < piece_pos::we_have_index);
|
TORRENT_ASSERT(m_piece_map.size() < piece_pos::we_have_index);
|
||||||
|
|
||||||
m_blocks_per_piece = blocks_per_piece;
|
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;
|
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);
|
TORRENT_ASSERT(m_blocks_in_last_piece <= m_blocks_per_piece);
|
||||||
|
|
|
@ -744,7 +744,7 @@ namespace libtorrent
|
||||||
return m_torrent_file->add_merkle_nodes(nodes, piece);
|
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_offset = p.block_index * block_size();
|
||||||
int block = (std::min)(torrent_file().piece_size(
|
int block = (std::min)(torrent_file().piece_size(
|
||||||
|
@ -817,14 +817,6 @@ namespace libtorrent
|
||||||
return;
|
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
|
// the shared_from_this() will create an intentional
|
||||||
// cycle of ownership, se the hpp file for description.
|
// cycle of ownership, se the hpp file for description.
|
||||||
m_owning_storage = new piece_manager(shared_from_this(), m_torrent_file
|
m_owning_storage = new piece_manager(shared_from_this(), m_torrent_file
|
||||||
|
@ -834,8 +826,10 @@ namespace libtorrent
|
||||||
|
|
||||||
if (has_picker())
|
if (has_picker())
|
||||||
{
|
{
|
||||||
m_picker->init((std::max)(m_torrent_file->piece_length() / block_size(), 1)
|
int blocks_per_piece = (m_torrent_file->piece_length() + block_size() - 1) / block_size();
|
||||||
, int((m_torrent_file->total_size()+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();
|
std::vector<std::string> const& url_seeds = m_torrent_file->url_seeds();
|
||||||
|
@ -1153,8 +1147,11 @@ namespace libtorrent
|
||||||
m_owning_storage->async_release_files();
|
m_owning_storage->async_release_files();
|
||||||
if (!m_picker) m_picker.reset(new piece_picker());
|
if (!m_picker) m_picker.reset(new piece_picker());
|
||||||
std::fill(m_file_progress.begin(), m_file_progress.end(), 0);
|
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
|
// assume that we don't have anything
|
||||||
TORRENT_ASSERT(m_picker->num_have() == 0);
|
TORRENT_ASSERT(m_picker->num_have() == 0);
|
||||||
m_files_checked = false;
|
m_files_checked = false;
|
||||||
|
@ -1972,11 +1969,8 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
#ifdef TORRENT_DEBUG
|
#ifdef TORRENT_DEBUG
|
||||||
TORRENT_ASSERT(p->bytes_downloaded <= p->full_block_bytes);
|
TORRENT_ASSERT(p->bytes_downloaded <= p->full_block_bytes);
|
||||||
if (p->piece_index == last_piece_index
|
TORRENT_ASSERT(p->full_block_bytes == to_req(piece_block(
|
||||||
&& p->block_index == m_torrent_file->piece_size(last_piece) / block_size())
|
p->piece_index, p->block_index)).length);
|
||||||
TORRENT_ASSERT(p->full_block_bytes == m_torrent_file->piece_size(last_piece) % block_size());
|
|
||||||
else
|
|
||||||
TORRENT_ASSERT(p->full_block_bytes == block_size());
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
for (std::map<piece_block, int>::iterator i = downloading_piece.begin();
|
for (std::map<piece_block, int>::iterator i = downloading_piece.begin();
|
||||||
|
@ -4856,7 +4850,6 @@ namespace libtorrent
|
||||||
if (m_files_checked && valid_metadata())
|
if (m_files_checked && valid_metadata())
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(block_size() > 0);
|
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);
|
// if (is_seed()) TORRENT_ASSERT(m_picker.get() == 0);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue