libtorrent sync 1531
This commit is contained in:
parent
f1fde2dcf0
commit
0e3f5672a5
|
@ -36,7 +36,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <memory>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <typeinfo>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -56,6 +55,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include "libtorrent/time.hpp"
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
#ifndef TORRENT_MAX_ALERT_TYPES
|
||||
#define TORRENT_MAX_ALERT_TYPES 15
|
||||
|
|
|
@ -33,15 +33,17 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef TORRENT_ASSERT_HPP_INCLUDED
|
||||
#define TORRENT_ASSERT_HPP_INCLUDED
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#ifndef NDEBUG
|
||||
#if defined __linux__ && defined _GNUC
|
||||
#if defined __linux__ && defined __GNUC__
|
||||
#ifdef assert
|
||||
#undef assert
|
||||
#endif
|
||||
|
||||
void assert_fail(int line, char const* file);
|
||||
void assert_fail(const char* expr, int line, char const* file, char const* function);
|
||||
|
||||
#define assert(x) if (!(x)) assert_fail(__LINE__, __FILE__)
|
||||
#define assert(x) if (!(x)) assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__)
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -240,7 +240,7 @@ namespace libtorrent
|
|||
bool is_listening() const;
|
||||
|
||||
torrent_handle add_torrent(
|
||||
torrent_info const& ti
|
||||
boost::intrusive_ptr<torrent_info> ti
|
||||
, fs::path const& save_path
|
||||
, entry const& resume_data
|
||||
, bool compact_mode
|
||||
|
|
|
@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define TORRENT_CONFIG_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 4
|
||||
|
||||
|
|
|
@ -64,10 +64,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <list>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
|
||||
#include "libtorrent/size_type.hpp"
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
|
|
@ -33,11 +33,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef TORRENT_HASHER_HPP_INCLUDED
|
||||
#define TORRENT_HASHER_HPP_INCLUDED
|
||||
|
||||
#include <cassert>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
#include "libtorrent/peer_id.hpp"
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/assert.hpp"
|
||||
#include "zlib.h"
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
|
|
|
@ -34,14 +34,17 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define TORRENT_INTRUSIVE_PTR_BASE
|
||||
|
||||
#include <boost/detail/atomic_count.hpp>
|
||||
#include <cassert>
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
template<class T>
|
||||
struct intrusive_ptr_base
|
||||
{
|
||||
intrusive_ptr_base(const intrusive_ptr_base<T>& b)
|
||||
: m_refs(0) {}
|
||||
|
||||
friend void intrusive_ptr_add_ref(intrusive_ptr_base<T> const* s)
|
||||
{
|
||||
assert(s->m_refs >= 0);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#ifndef TORRENT_INVARIANT_ACCESS_HPP_INCLUDED
|
||||
#define TORRENT_INVARIANT_ACCESS_HPP_INCLUDED
|
||||
|
||||
#include <cassert>
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
|
|
@ -34,7 +34,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define NODE_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
|
@ -45,6 +44,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include <libtorrent/io.hpp>
|
||||
#include <libtorrent/session_settings.hpp>
|
||||
#include <libtorrent/assert.hpp>
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
|
|
@ -33,10 +33,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define NODE_ID_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
#include "libtorrent/peer_id.hpp"
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
namespace libtorrent { namespace dht
|
||||
{
|
||||
|
|
|
@ -35,13 +35,12 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef TORRENT_PE_CRYPTO_HPP_INCLUDED
|
||||
#define TORRENT_PE_CRYPTO_HPP_INCLUDED
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/rc4.h>
|
||||
|
||||
#include "peer_id.hpp" // For sha1_hash
|
||||
#include "libtorrent/peer_id.hpp" // For sha1_hash
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
|
|
@ -152,11 +152,15 @@ namespace libtorrent
|
|||
int upload_limit() const { return m_upload_limit; }
|
||||
int download_limit() const { return m_download_limit; }
|
||||
|
||||
bool prefer_whole_pieces() const
|
||||
{ return m_prefer_whole_pieces; }
|
||||
int prefer_whole_pieces() const
|
||||
{
|
||||
if (m_prefer_whole_pieces == 0)
|
||||
return peer_info_struct() && peer_info_struct()->on_parole ? 1 : 0;
|
||||
return m_prefer_whole_pieces;
|
||||
}
|
||||
|
||||
void prefer_whole_pieces(bool b)
|
||||
{ m_prefer_whole_pieces = b; }
|
||||
void prefer_whole_pieces(int num)
|
||||
{ m_prefer_whole_pieces = num; }
|
||||
|
||||
bool request_large_blocks() const
|
||||
{ return m_request_large_blocks; }
|
||||
|
@ -219,6 +223,7 @@ namespace libtorrent
|
|||
|
||||
std::vector<bool> const& get_bitfield() const;
|
||||
std::vector<int> const& allowed_fast();
|
||||
std::vector<int> const& suggested_pieces() const { return m_suggested_pieces; }
|
||||
|
||||
void timed_out();
|
||||
// this will cause this peer_connection to be disconnected.
|
||||
|
@ -303,6 +308,7 @@ namespace libtorrent
|
|||
void incoming_have_all();
|
||||
void incoming_have_none();
|
||||
void incoming_allowed_fast(int index);
|
||||
void incoming_suggest(int index);
|
||||
|
||||
// the following functions appends messages
|
||||
// to the send buffer
|
||||
|
@ -493,6 +499,11 @@ namespace libtorrent
|
|||
// the time we sent a request to
|
||||
// this peer the last time
|
||||
ptime m_last_request;
|
||||
// the time we received the last
|
||||
// piece request from the peer
|
||||
ptime m_last_incoming_request;
|
||||
// the time when we unchoked this peer
|
||||
ptime m_last_unchoke;
|
||||
|
||||
int m_packet_size;
|
||||
int m_recv_pos;
|
||||
|
@ -590,7 +601,7 @@ namespace libtorrent
|
|||
std::deque<peer_request> m_requests;
|
||||
|
||||
// the blocks we have reserved in the piece
|
||||
// picker and will send to this peer.
|
||||
// picker and will request from this peer.
|
||||
std::deque<piece_block> m_request_queue;
|
||||
|
||||
// the queue of blocks we have requested
|
||||
|
@ -658,12 +669,13 @@ namespace libtorrent
|
|||
bool m_writing;
|
||||
bool m_reading;
|
||||
|
||||
// if set to true, this peer will always prefer
|
||||
// to request entire pieces, rather than blocks.
|
||||
// if it is false, the download rate limit setting
|
||||
// if set to non-zero, this peer will always prefer
|
||||
// to request entire n pieces, rather than blocks.
|
||||
// where n is the value of this variable.
|
||||
// if it is 0, the download rate limit setting
|
||||
// will be used to determine if whole pieces
|
||||
// are preferred.
|
||||
bool m_prefer_whole_pieces;
|
||||
int m_prefer_whole_pieces;
|
||||
|
||||
// if this is true, the blocks picked by the piece
|
||||
// picker will be merged before passed to the
|
||||
|
@ -718,6 +730,10 @@ namespace libtorrent
|
|||
// requested (regardless of choke state)
|
||||
std::vector<int> m_allowed_fast;
|
||||
|
||||
// pieces that has been suggested to be
|
||||
// downloaded from this peer
|
||||
std::vector<int> m_suggested_pieces;
|
||||
|
||||
// the number of bytes send to the disk-io
|
||||
// thread that hasn't yet been completely written.
|
||||
int m_outstanding_writing_bytes;
|
||||
|
|
|
@ -35,12 +35,12 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
|
|
@ -35,7 +35,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -52,6 +51,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/socket.hpp"
|
||||
#include "libtorrent/session_settings.hpp"
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
@ -191,9 +191,9 @@ namespace libtorrent
|
|||
// THIS IS DONE BY THE peer_connection::send_request() MEMBER FUNCTION!
|
||||
// The last argument is the policy::peer pointer for the peer that
|
||||
// we'll download from.
|
||||
void pick_pieces(const std::vector<bool>& pieces
|
||||
void pick_pieces(std::vector<bool> const& pieces
|
||||
, std::vector<piece_block>& interesting_blocks
|
||||
, int num_pieces, bool prefer_whole_pieces
|
||||
, int num_pieces, int prefer_whole_pieces
|
||||
, void* peer, piece_state_t speed
|
||||
, bool rarest_first) const;
|
||||
|
||||
|
@ -202,11 +202,11 @@ namespace libtorrent
|
|||
// are added to interesting_blocks, and busy blocks are
|
||||
// added to backup_blocks. num blocks is the number of
|
||||
// blocks to be picked.
|
||||
int add_interesting_blocks(const std::vector<int>& piece_list
|
||||
int add_interesting_blocks(std::vector<int> const& piece_list
|
||||
, const std::vector<bool>& pieces
|
||||
, std::vector<piece_block>& interesting_blocks
|
||||
, std::vector<piece_block>& backup_blocks
|
||||
, int num_blocks, bool prefer_whole_pieces
|
||||
, int num_blocks, int prefer_whole_pieces
|
||||
, void* peer, piece_state_t speed
|
||||
, bool ignore_downloading_pieces) const;
|
||||
|
||||
|
@ -284,6 +284,9 @@ namespace libtorrent
|
|||
|
||||
private:
|
||||
|
||||
std::pair<int, int> expand_piece(int piece, int whole_pieces
|
||||
, std::vector<bool> const& have) const;
|
||||
|
||||
struct piece_pos
|
||||
{
|
||||
piece_pos() {}
|
||||
|
|
|
@ -142,6 +142,14 @@ namespace libtorrent
|
|||
, entry const& resume_data = entry()
|
||||
, bool compact_mode = true
|
||||
, bool paused = false
|
||||
, storage_constructor_type sc = default_storage_constructor) TORRENT_DEPRECATED;
|
||||
|
||||
torrent_handle add_torrent(
|
||||
boost::intrusive_ptr<torrent_info> ti
|
||||
, fs::path const& save_path
|
||||
, entry const& resume_data = entry()
|
||||
, bool compact_mode = true
|
||||
, bool paused = false
|
||||
, storage_constructor_type sc = default_storage_constructor);
|
||||
|
||||
torrent_handle add_torrent(
|
||||
|
|
|
@ -43,6 +43,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <boost/limits.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -147,10 +148,11 @@ namespace libtorrent
|
|||
};
|
||||
|
||||
typedef storage_interface* (&storage_constructor_type)(
|
||||
torrent_info const&, fs::path const&
|
||||
boost::intrusive_ptr<torrent_info const>, fs::path const&
|
||||
, file_pool&);
|
||||
|
||||
TORRENT_EXPORT storage_interface* default_storage_constructor(torrent_info const& ti
|
||||
TORRENT_EXPORT storage_interface* default_storage_constructor(
|
||||
boost::intrusive_ptr<torrent_info const> ti
|
||||
, fs::path const& path, file_pool& fp);
|
||||
|
||||
// returns true if the filesystem the path relies on supports
|
||||
|
@ -169,7 +171,7 @@ namespace libtorrent
|
|||
|
||||
piece_manager(
|
||||
boost::shared_ptr<void> const& torrent
|
||||
, torrent_info const& ti
|
||||
, boost::intrusive_ptr<torrent_info const> ti
|
||||
, fs::path const& path
|
||||
, file_pool& fp
|
||||
, disk_io_thread& io
|
||||
|
@ -227,7 +229,7 @@ namespace libtorrent
|
|||
{ return m_compact_mode; }
|
||||
|
||||
#ifndef NDEBUG
|
||||
std::string name() const { return m_info.name(); }
|
||||
std::string name() const { return m_info->name(); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
@ -283,7 +285,7 @@ namespace libtorrent
|
|||
// a bitmask representing the pieces we have
|
||||
std::vector<bool> m_have_piece;
|
||||
|
||||
torrent_info const& m_info;
|
||||
boost::intrusive_ptr<torrent_info const> m_info;
|
||||
|
||||
// slots that haven't had any file storage allocated
|
||||
std::vector<int> m_unallocated_slots;
|
||||
|
@ -313,12 +315,6 @@ namespace libtorrent
|
|||
|
||||
mutable boost::recursive_mutex m_mutex;
|
||||
|
||||
bool m_allocating;
|
||||
boost::mutex m_allocating_monitor;
|
||||
boost::condition m_allocating_condition;
|
||||
|
||||
// these states are used while checking/allocating the torrent
|
||||
|
||||
enum {
|
||||
// the default initial state
|
||||
state_none,
|
||||
|
@ -333,6 +329,11 @@ namespace libtorrent
|
|||
} m_state;
|
||||
int m_current_slot;
|
||||
|
||||
// this is saved in case we need to instantiate a new
|
||||
// storage (osed when remapping files)
|
||||
storage_constructor_type m_storage_constructor;
|
||||
|
||||
// temporary buffer used while checking
|
||||
std::vector<char> m_piece_data;
|
||||
|
||||
// this maps a piece hash to piece index. It will be
|
||||
|
@ -340,6 +341,8 @@ namespace libtorrent
|
|||
// isn't needed)
|
||||
std::multimap<sha1_hash, int> m_hash_to_piece;
|
||||
|
||||
// this map contains partial hashes for downloading
|
||||
// pieces.
|
||||
std::map<int, partial_hash> m_piece_hasher;
|
||||
|
||||
disk_io_thread& m_io_thread;
|
||||
|
|
|
@ -97,7 +97,7 @@ namespace libtorrent
|
|||
torrent(
|
||||
aux::session_impl& ses
|
||||
, aux::checker_impl& checker
|
||||
, torrent_info const& tf
|
||||
, boost::intrusive_ptr<torrent_info> tf
|
||||
, fs::path const& save_path
|
||||
, tcp::endpoint const& net_interface
|
||||
, bool compact_mode
|
||||
|
@ -469,14 +469,14 @@ namespace libtorrent
|
|||
bool is_seed() const
|
||||
{
|
||||
return valid_metadata()
|
||||
&& m_num_pieces == m_torrent_file.num_pieces();
|
||||
&& m_num_pieces == m_torrent_file->num_pieces();
|
||||
}
|
||||
|
||||
// this is true if we have all the pieces that we want
|
||||
bool is_finished() const
|
||||
{
|
||||
if (is_seed()) return true;
|
||||
return valid_metadata() && m_torrent_file.num_pieces()
|
||||
return valid_metadata() && m_torrent_file->num_pieces()
|
||||
- m_num_pieces - m_picker->num_filtered() == 0;
|
||||
}
|
||||
|
||||
|
@ -498,7 +498,7 @@ namespace libtorrent
|
|||
}
|
||||
piece_manager& filesystem();
|
||||
torrent_info const& torrent_file() const
|
||||
{ return m_torrent_file; }
|
||||
{ return *m_torrent_file; }
|
||||
|
||||
std::vector<announce_entry> const& trackers() const
|
||||
{ return m_trackers; }
|
||||
|
@ -539,7 +539,7 @@ namespace libtorrent
|
|||
bool ready_for_connections() const
|
||||
{ return m_connections_initialized; }
|
||||
bool valid_metadata() const
|
||||
{ return m_torrent_file.is_valid(); }
|
||||
{ return m_torrent_file->is_valid(); }
|
||||
|
||||
// parses the info section from the given
|
||||
// bencoded tree and moves the torrent
|
||||
|
@ -563,7 +563,7 @@ namespace libtorrent
|
|||
|
||||
void update_peer_interest();
|
||||
|
||||
torrent_info m_torrent_file;
|
||||
boost::intrusive_ptr<torrent_info> m_torrent_file;
|
||||
|
||||
// is set to true when the torrent has
|
||||
// been aborted.
|
||||
|
|
|
@ -57,6 +57,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/peer_request.hpp"
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/time.hpp"
|
||||
#include "libtorrent/intrusive_ptr_base.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
@ -96,7 +97,7 @@ namespace libtorrent
|
|||
virtual const char* what() const throw() { return "invalid torrent file"; }
|
||||
};
|
||||
|
||||
class TORRENT_EXPORT torrent_info
|
||||
class TORRENT_EXPORT torrent_info : public intrusive_ptr_base<torrent_info>
|
||||
{
|
||||
public:
|
||||
|
||||
|
|
|
@ -32,9 +32,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#ifndef NDEBUG
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <execinfo.h>
|
||||
|
||||
void assert_fail(int line, char const* file)
|
||||
void assert_fail(char const* expr, int line, char const* file, char const* function)
|
||||
{
|
||||
|
||||
fprintf(stderr, "assertion failed. Please file a bugreport at "
|
||||
|
@ -42,9 +44,11 @@ void assert_fail(int line, char const* file)
|
|||
"Please include the following information:\n\n"
|
||||
"file: '%s'\n"
|
||||
"line: %d\n"
|
||||
"stack:\n", file, line);
|
||||
"function: %s\n"
|
||||
"expression: %s\n"
|
||||
"stack:\n", file, line, function, expr);
|
||||
|
||||
void* stacktrace[50];
|
||||
void* stack[50];
|
||||
int size = backtrace(stack, 50);
|
||||
char** symbols = backtrace_symbols(stack, size);
|
||||
|
||||
|
@ -54,6 +58,7 @@ void assert_fail(int line, char const* file)
|
|||
}
|
||||
|
||||
free(symbols);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1062,8 +1062,14 @@ namespace libtorrent
|
|||
if (!m_supports_fast)
|
||||
throw protocol_error("got 'suggest_piece' without FAST extension support");
|
||||
|
||||
// just ignore for now
|
||||
return;
|
||||
m_statistics.received_bytes(0, received);
|
||||
if (!packet_finished()) return;
|
||||
|
||||
buffer::const_interval recv_buffer = receive_buffer();
|
||||
|
||||
const char* ptr = recv_buffer.begin + 1;
|
||||
int piece = detail::read_uint32(ptr);
|
||||
incoming_suggest(piece);
|
||||
}
|
||||
|
||||
void bt_peer_connection::on_have_all(int received)
|
||||
|
|
|
@ -31,9 +31,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
*/
|
||||
|
||||
#include "libtorrent/pch.hpp"
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
|
|
@ -34,10 +34,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
#include <cassert>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include "libtorrent/kademlia/node_id.hpp"
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
using boost::bind;
|
||||
|
||||
|
|
|
@ -32,13 +32,13 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/engine.h>
|
||||
|
||||
#include "libtorrent/pe_crypto.hpp"
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
namespace libtorrent {
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/aux_/session_impl.hpp"
|
||||
#include "libtorrent/policy.hpp"
|
||||
#include "libtorrent/socket_type.hpp"
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
using boost::bind;
|
||||
using boost::shared_ptr;
|
||||
|
@ -76,6 +77,8 @@ namespace libtorrent
|
|||
, m_timeout(m_ses.settings().peer_timeout)
|
||||
, m_last_piece(time_now())
|
||||
, m_last_request(time_now())
|
||||
, m_last_incoming_request(min_time())
|
||||
, m_last_unchoke(min_time())
|
||||
, m_packet_size(0)
|
||||
, m_recv_pos(0)
|
||||
, m_current_send_buffer(0)
|
||||
|
@ -154,6 +157,8 @@ namespace libtorrent
|
|||
, m_timeout(m_ses.settings().peer_timeout)
|
||||
, m_last_piece(time_now())
|
||||
, m_last_request(time_now())
|
||||
, m_last_incoming_request(min_time())
|
||||
, m_last_unchoke(min_time())
|
||||
, m_packet_size(0)
|
||||
, m_recv_pos(0)
|
||||
, m_current_send_buffer(0)
|
||||
|
@ -338,7 +343,7 @@ namespace libtorrent
|
|||
// if this is a web seed. we don't have a peer_info struct
|
||||
if (m_peer_info) m_peer_info->seed = true;
|
||||
// if we're a seed too, disconnect
|
||||
if (t->is_seed())
|
||||
if (t->is_finished())
|
||||
{
|
||||
throw std::runtime_error("seed to seed connection redundant, disconnecting");
|
||||
}
|
||||
|
@ -395,7 +400,12 @@ namespace libtorrent
|
|||
{
|
||||
// dont announce during handshake
|
||||
if (in_handshake()) return;
|
||||
|
||||
|
||||
// remove suggested pieces that we have
|
||||
std::vector<int>::iterator i = std::find(
|
||||
m_suggested_pieces.begin(), m_suggested_pieces.end(), index);
|
||||
if (i != m_suggested_pieces.end()) m_suggested_pieces.erase(i);
|
||||
|
||||
// optimization, don't send have messages
|
||||
// to peers that already have the piece
|
||||
if (!m_ses.settings().send_redundant_have
|
||||
|
@ -511,6 +521,7 @@ namespace libtorrent
|
|||
assert(t);
|
||||
|
||||
assert(t->valid_metadata());
|
||||
torrent_info const& ti = t->torrent_file();
|
||||
|
||||
return p.piece >= 0
|
||||
&& p.piece < t->torrent_file().num_pieces()
|
||||
|
@ -518,11 +529,13 @@ namespace libtorrent
|
|||
&& p.start >= 0
|
||||
&& (p.length == t->block_size()
|
||||
|| (p.length < t->block_size()
|
||||
&& p.piece == t->torrent_file().num_pieces()-1
|
||||
&& p.start + p.length == t->torrent_file().piece_size(p.piece))
|
||||
&& p.piece == ti.num_pieces()-1
|
||||
&& p.start + p.length == ti.piece_size(p.piece))
|
||||
|| (m_request_large_blocks
|
||||
&& p.length <= t->torrent_file().piece_size(p.piece)))
|
||||
&& p.start + p.length <= t->torrent_file().piece_size(p.piece)
|
||||
&& 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);
|
||||
}
|
||||
|
||||
|
@ -723,6 +736,33 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// -------- REJECT PIECE -------
|
||||
// -----------------------------
|
||||
|
||||
void peer_connection::incoming_suggest(int index)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string()
|
||||
<< " <== SUGGEST_PIECE [ piece: " << index << " ]\n";
|
||||
#endif
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
if (!t) return;
|
||||
|
||||
if (t->have_piece(index)) return;
|
||||
|
||||
if (m_suggested_pieces.size() > 9)
|
||||
m_suggested_pieces.erase(m_suggested_pieces.begin());
|
||||
m_suggested_pieces.push_back(index);
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string()
|
||||
<< " ** SUGGEST_PIECE [ piece: " << index << " added to set: " << m_suggested_pieces.size() << " ]\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// ---------- UNCHOKE ----------
|
||||
// -----------------------------
|
||||
|
@ -877,7 +917,7 @@ namespace libtorrent
|
|||
{
|
||||
assert(m_peer_info);
|
||||
m_peer_info->seed = true;
|
||||
if (t->is_seed())
|
||||
if (t->is_finished())
|
||||
{
|
||||
throw protocol_error("seed to seed connection redundant, disconnecting");
|
||||
}
|
||||
|
@ -948,7 +988,7 @@ namespace libtorrent
|
|||
// if this is a web seed. we don't have a peer_info struct
|
||||
if (m_peer_info) m_peer_info->seed = true;
|
||||
// if we're a seed too, disconnect
|
||||
if (t->is_seed())
|
||||
if (t->is_finished())
|
||||
{
|
||||
throw protocol_error("seed to seed connection redundant, disconnecting");
|
||||
}
|
||||
|
@ -1096,6 +1136,7 @@ namespace libtorrent
|
|||
else
|
||||
{
|
||||
m_requests.push_back(r);
|
||||
m_last_incoming_request = time_now();
|
||||
fill_send_buffer();
|
||||
}
|
||||
}
|
||||
|
@ -1476,7 +1517,7 @@ namespace libtorrent
|
|||
#endif
|
||||
|
||||
// if we're a seed too, disconnect
|
||||
if (t->is_seed())
|
||||
if (t->is_finished())
|
||||
throw protocol_error("seed to seed connection redundant, disconnecting");
|
||||
|
||||
assert(!m_have_piece.empty());
|
||||
|
@ -1585,6 +1626,7 @@ namespace libtorrent
|
|||
assert(block.block_index >= 0);
|
||||
assert(block.block_index < t->torrent_file().piece_size(block.piece_index));
|
||||
assert(!t->picker().is_requested(block) || (t->picker().num_peers(block) > 0));
|
||||
assert(!t->have_piece(block.piece_index));
|
||||
|
||||
piece_picker::piece_state_t state;
|
||||
peer_speed_t speed = peer_speed();
|
||||
|
@ -1701,6 +1743,7 @@ namespace libtorrent
|
|||
INVARIANT_CHECK;
|
||||
|
||||
if (!m_choked) return;
|
||||
m_last_unchoke = time_now();
|
||||
write_unchoke();
|
||||
m_choked = false;
|
||||
|
||||
|
@ -1776,21 +1819,27 @@ namespace libtorrent
|
|||
// blocks that are in the same piece into larger requests
|
||||
if (m_request_large_blocks)
|
||||
{
|
||||
while (!m_request_queue.empty()
|
||||
&& m_request_queue.front().piece_index == r.piece
|
||||
&& m_request_queue.front().block_index == block.block_index + 1)
|
||||
int blocks_per_piece = t->torrent_file().piece_length() / t->block_size();
|
||||
|
||||
while (!m_request_queue.empty())
|
||||
{
|
||||
// check to see if this block is connected to the previous one
|
||||
// if it is, merge them, otherwise, break this merge loop
|
||||
piece_block const& front = m_request_queue.front();
|
||||
if (front.piece_index * blocks_per_piece + front.block_index
|
||||
!= block.piece_index * blocks_per_piece + block.block_index + 1)
|
||||
break;
|
||||
block = m_request_queue.front();
|
||||
m_request_queue.pop_front();
|
||||
m_download_queue.push_back(block);
|
||||
/*
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string()
|
||||
<< " *** REQUEST-QUEUE** [ "
|
||||
<< " *** MERGING REQUEST ** [ "
|
||||
"piece: " << block.piece_index << " | "
|
||||
"block: " << block.block_index << " ]\n";
|
||||
#endif
|
||||
*/
|
||||
|
||||
block_offset = block.block_index * t->block_size();
|
||||
block_size = (std::min)((int)t->torrent_file().piece_size(
|
||||
block.piece_index) - block_offset, t->block_size());
|
||||
|
@ -2137,7 +2186,7 @@ namespace libtorrent
|
|||
// maintain the share ratio given by m_ratio
|
||||
// with all peers.
|
||||
|
||||
if (t->is_seed() || is_choked() || t->ratio() == 0.0f)
|
||||
if (t->is_finished() || is_choked() || t->ratio() == 0.0f)
|
||||
{
|
||||
// if we have downloaded more than one piece more
|
||||
// than we have uploaded OR if we are a seed
|
||||
|
@ -2862,9 +2911,20 @@ namespace libtorrent
|
|||
// if the peer hasn't said a thing for a certain
|
||||
// time, it is considered to have timed out
|
||||
time_duration d;
|
||||
d = time_now() - m_last_receive;
|
||||
d = now - m_last_receive;
|
||||
if (d > seconds(m_timeout)) return true;
|
||||
|
||||
// disconnect peers that we unchoked, but
|
||||
// they didn't send a request within 20 seconds.
|
||||
// but only if we're a seed
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
d = now - (std::max)(m_last_unchoke, m_last_incoming_request);
|
||||
if (m_requests.empty()
|
||||
&& !m_choked
|
||||
&& m_peer_interested
|
||||
&& t && t->is_finished()
|
||||
&& d > seconds(20)) return true;
|
||||
|
||||
// TODO: as long as we have less than 95% of the
|
||||
// global (or local) connection limit, connections should
|
||||
// never time out for another reason
|
||||
|
|
|
@ -201,7 +201,7 @@ namespace libtorrent
|
|||
, end(in.end()); i != end; ++i)
|
||||
{
|
||||
m_piece_map[*i].index = c++;
|
||||
assert(m_piece_map[*i].priority(old_limit) == old_limit);
|
||||
assert(m_piece_map[*i].priority(old_limit) == old_limit * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1079,7 +1079,7 @@ namespace libtorrent
|
|||
// or slow once they're started.
|
||||
void piece_picker::pick_pieces(const std::vector<bool>& pieces
|
||||
, std::vector<piece_block>& interesting_blocks
|
||||
, int num_blocks, bool prefer_whole_pieces
|
||||
, int num_blocks, int prefer_whole_pieces
|
||||
, void* peer, piece_state_t speed, bool rarest_first) const
|
||||
{
|
||||
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
|
||||
|
@ -1102,7 +1102,7 @@ namespace libtorrent
|
|||
// ignored as long as possible. All blocks found in downloading
|
||||
// pieces are regarded as backup blocks
|
||||
bool ignore_downloading_pieces = false;
|
||||
if (prefer_whole_pieces)
|
||||
if (prefer_whole_pieces > 0 || !rarest_first)
|
||||
{
|
||||
std::vector<int> downloading_pieces;
|
||||
downloading_pieces.reserve(m_downloads.size());
|
||||
|
@ -1111,34 +1111,46 @@ namespace libtorrent
|
|||
{
|
||||
downloading_pieces.push_back(i->index);
|
||||
}
|
||||
add_interesting_blocks(downloading_pieces, pieces
|
||||
, backup_blocks, backup_blocks, num_blocks
|
||||
, prefer_whole_pieces, peer, speed, ignore_downloading_pieces);
|
||||
if (prefer_whole_pieces > 0)
|
||||
{
|
||||
add_interesting_blocks(downloading_pieces, pieces
|
||||
, backup_blocks, backup_blocks, num_blocks
|
||||
, prefer_whole_pieces, peer, speed, ignore_downloading_pieces);
|
||||
}
|
||||
else
|
||||
{
|
||||
num_blocks = add_interesting_blocks(downloading_pieces, pieces
|
||||
, interesting_blocks, backup_blocks, num_blocks
|
||||
, prefer_whole_pieces, peer, speed, ignore_downloading_pieces);
|
||||
}
|
||||
ignore_downloading_pieces = true;
|
||||
}
|
||||
|
||||
// this loop will loop from pieces with priority 1 and up
|
||||
// until we either reach the end of the piece list or
|
||||
// has filled the interesting_blocks with num_blocks
|
||||
// blocks.
|
||||
|
||||
// +1 is to ignore pieces that no peer has. The bucket with index 0 contains
|
||||
// pieces that 0 other peers have. bucket will point to a bucket with
|
||||
// pieces with the same priority. It will be iterated in priority
|
||||
// order (high priority/rare pices first). The content of each
|
||||
// bucket is randomized
|
||||
for (std::vector<std::vector<int> >::const_iterator bucket
|
||||
= m_piece_info.begin() + 1; bucket != m_piece_info.end();
|
||||
++bucket)
|
||||
if (rarest_first)
|
||||
{
|
||||
if (bucket->empty()) continue;
|
||||
num_blocks = add_interesting_blocks(*bucket, pieces
|
||||
, interesting_blocks, backup_blocks, num_blocks
|
||||
, prefer_whole_pieces, peer, speed, ignore_downloading_pieces);
|
||||
assert(num_blocks >= 0);
|
||||
if (num_blocks == 0) return;
|
||||
if (rarest_first) continue;
|
||||
// this loop will loop from pieces with priority 1 and up
|
||||
// until we either reach the end of the piece list or
|
||||
// has filled the interesting_blocks with num_blocks
|
||||
// blocks.
|
||||
|
||||
// +1 is to ignore pieces that no peer has. The bucket with index 0 contains
|
||||
// pieces that 0 other peers have. bucket will point to a bucket with
|
||||
// pieces with the same priority. It will be iterated in priority
|
||||
// order (high priority/rare pices first). The content of each
|
||||
// bucket is randomized
|
||||
for (std::vector<std::vector<int> >::const_iterator bucket
|
||||
= m_piece_info.begin() + 1; num_blocks > 0 && bucket != m_piece_info.end();
|
||||
++bucket)
|
||||
{
|
||||
if (bucket->empty()) continue;
|
||||
num_blocks = add_interesting_blocks(*bucket, pieces
|
||||
, interesting_blocks, backup_blocks, num_blocks
|
||||
, prefer_whole_pieces, peer, speed, ignore_downloading_pieces);
|
||||
assert(num_blocks >= 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we're not using rarest first (only for the first
|
||||
// bucket, since that's where the currently downloading
|
||||
// pieces are)
|
||||
|
@ -1147,8 +1159,9 @@ namespace libtorrent
|
|||
while (num_blocks > 0)
|
||||
{
|
||||
while (!pieces[piece]
|
||||
|| m_piece_map[piece].index == piece_pos::we_have_index
|
||||
|| m_piece_map[piece].priority(m_sequenced_download_threshold) < 2)
|
||||
|| m_piece_map[piece].have()
|
||||
|| m_piece_map[piece].downloading
|
||||
|| m_piece_map[piece].filtered())
|
||||
{
|
||||
++piece;
|
||||
if (piece == int(m_piece_map.size())) piece = 0;
|
||||
|
@ -1158,23 +1171,28 @@ namespace libtorrent
|
|||
|
||||
assert(m_piece_map[piece].downloading == false);
|
||||
|
||||
int num_blocks_in_piece = blocks_in_piece(piece);
|
||||
|
||||
if (!prefer_whole_pieces && num_blocks_in_piece > num_blocks)
|
||||
num_blocks_in_piece = num_blocks;
|
||||
for (int j = 0; j < num_blocks_in_piece; ++j)
|
||||
interesting_blocks.push_back(piece_block(piece, j));
|
||||
num_blocks -= (std::min)(num_blocks_in_piece, num_blocks);
|
||||
++piece;
|
||||
int start, end;
|
||||
boost::tie(start, end) = expand_piece(piece, prefer_whole_pieces, pieces);
|
||||
for (int k = start; k < end; ++k)
|
||||
{
|
||||
int num_blocks_in_piece = blocks_in_piece(k);
|
||||
if (prefer_whole_pieces == 0 && num_blocks_in_piece > num_blocks)
|
||||
num_blocks_in_piece = num_blocks;
|
||||
for (int j = 0; j < num_blocks_in_piece; ++j)
|
||||
{
|
||||
interesting_blocks.push_back(piece_block(k, j));
|
||||
--num_blocks;
|
||||
}
|
||||
}
|
||||
piece = end;
|
||||
if (piece == int(m_piece_map.size())) piece = 0;
|
||||
// could not find any more pieces
|
||||
if (piece == start_piece) return;
|
||||
}
|
||||
if (num_blocks == 0) return;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
assert(num_blocks > 0);
|
||||
if (num_blocks <= 0) return;
|
||||
|
||||
if (!backup_blocks.empty())
|
||||
interesting_blocks.insert(interesting_blocks.end()
|
||||
|
@ -1222,7 +1240,7 @@ namespace libtorrent
|
|||
, std::vector<bool> const& pieces
|
||||
, std::vector<piece_block>& interesting_blocks
|
||||
, std::vector<piece_block>& backup_blocks
|
||||
, int num_blocks, bool prefer_whole_pieces
|
||||
, int num_blocks, int prefer_whole_pieces
|
||||
, void* peer, piece_state_t speed
|
||||
, bool ignore_downloading_pieces) const
|
||||
{
|
||||
|
@ -1266,7 +1284,7 @@ namespace libtorrent
|
|||
// blocks to the backup list. If the prioritized
|
||||
// blocks aren't enough, blocks from this list
|
||||
// will be picked.
|
||||
if (prefer_whole_pieces && !exclusive)
|
||||
if (prefer_whole_pieces > 0 && !exclusive)
|
||||
{
|
||||
for (int j = 0; j < num_blocks_in_piece; ++j)
|
||||
{
|
||||
|
@ -1321,7 +1339,7 @@ namespace libtorrent
|
|||
num_blocks--;
|
||||
// if we prefer whole pieces, continue picking from this
|
||||
// piece even though we have num_blocks
|
||||
if (prefer_whole_pieces) continue;
|
||||
if (prefer_whole_pieces > 0) continue;
|
||||
assert(num_blocks >= 0);
|
||||
if (num_blocks == 0) return num_blocks;
|
||||
}
|
||||
|
@ -1330,23 +1348,68 @@ namespace libtorrent
|
|||
backup_blocks.push_back(piece_block(*i, j));
|
||||
}
|
||||
}
|
||||
assert(num_blocks >= 0 || prefer_whole_pieces);
|
||||
assert(num_blocks >= 0 || prefer_whole_pieces > 0);
|
||||
if (num_blocks < 0) num_blocks = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!prefer_whole_pieces && num_blocks_in_piece > num_blocks)
|
||||
num_blocks_in_piece = num_blocks;
|
||||
for (int j = 0; j < num_blocks_in_piece; ++j)
|
||||
interesting_blocks.push_back(piece_block(*i, j));
|
||||
num_blocks -= (std::min)(num_blocks_in_piece, num_blocks);
|
||||
// pick a new piece
|
||||
if (prefer_whole_pieces == 0)
|
||||
{
|
||||
if (num_blocks_in_piece > num_blocks)
|
||||
num_blocks_in_piece = num_blocks;
|
||||
for (int j = 0; j < num_blocks_in_piece; ++j)
|
||||
interesting_blocks.push_back(piece_block(*i, j));
|
||||
num_blocks -= num_blocks_in_piece;
|
||||
}
|
||||
else
|
||||
{
|
||||
int start, end;
|
||||
boost::tie(start, end) = expand_piece(*i, prefer_whole_pieces, pieces);
|
||||
for (int k = start; k < end; ++k)
|
||||
{
|
||||
num_blocks_in_piece = blocks_in_piece(k);
|
||||
for (int j = 0; j < num_blocks_in_piece; ++j)
|
||||
{
|
||||
interesting_blocks.push_back(piece_block(k, j));
|
||||
--num_blocks;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(num_blocks >= 0);
|
||||
if (num_blocks == 0) return num_blocks;
|
||||
if (num_blocks <= 0) return num_blocks < 0 ? 0 : num_blocks;
|
||||
}
|
||||
return num_blocks;
|
||||
}
|
||||
|
||||
std::pair<int, int> piece_picker::expand_piece(int piece, int whole_pieces
|
||||
, std::vector<bool> const& have) const
|
||||
{
|
||||
if (whole_pieces == 0) return std::make_pair(piece, piece + 1);
|
||||
|
||||
int start = piece - 1;
|
||||
int lower_limit = piece - whole_pieces;
|
||||
if (lower_limit < -1) lower_limit = -1;
|
||||
while (start > lower_limit
|
||||
&& have[start]
|
||||
&& !m_piece_map[start].downloading
|
||||
&& !m_piece_map[start].filtered()
|
||||
&& !m_piece_map[start].have())
|
||||
--start;
|
||||
++start;
|
||||
assert(start >= 0);
|
||||
int end = piece + 1;
|
||||
int upper_limit = start + whole_pieces;
|
||||
if (upper_limit > int(m_piece_map.size())) upper_limit = int(m_piece_map.size());
|
||||
while (end < upper_limit
|
||||
&& have[end]
|
||||
&& !m_piece_map[end].downloading
|
||||
&& !m_piece_map[end].filtered()
|
||||
&& !m_piece_map[end].have())
|
||||
++end;
|
||||
return std::make_pair(start, end);
|
||||
}
|
||||
|
||||
bool piece_picker::is_piece_finished(int index) const
|
||||
{
|
||||
assert(index < (int)m_piece_map.size());
|
||||
|
@ -1432,6 +1495,7 @@ namespace libtorrent
|
|||
assert(block.block_index >= 0);
|
||||
assert(block.piece_index < (int)m_piece_map.size());
|
||||
assert(block.block_index < blocks_in_piece(block.piece_index));
|
||||
assert(!m_piece_map[block.piece_index].have());
|
||||
|
||||
piece_pos& p = m_piece_map[block.piece_index];
|
||||
if (p.downloading == 0)
|
||||
|
|
|
@ -209,16 +209,15 @@ namespace libtorrent
|
|||
std::vector<piece_block> interesting_pieces;
|
||||
interesting_pieces.reserve(100);
|
||||
|
||||
bool prefer_whole_pieces = c.prefer_whole_pieces()
|
||||
|| (c.peer_info_struct() && c.peer_info_struct()->on_parole);
|
||||
int prefer_whole_pieces = c.prefer_whole_pieces();
|
||||
|
||||
bool rarest_first = t.num_pieces() >= t.settings().initial_picker_threshold;
|
||||
|
||||
if (!prefer_whole_pieces)
|
||||
if (prefer_whole_pieces == 0)
|
||||
{
|
||||
prefer_whole_pieces = c.statistics().download_payload_rate()
|
||||
* t.settings().whole_pieces_threshold
|
||||
> t.torrent_file().piece_length();
|
||||
> t.torrent_file().piece_length() ? 1 : 0;
|
||||
}
|
||||
|
||||
// if we prefer whole pieces, the piece picker will pick at least
|
||||
|
@ -258,6 +257,18 @@ namespace libtorrent
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!c.suggested_pieces().empty())
|
||||
{
|
||||
// if the peer has suggested us to download certain pieces
|
||||
// try to pick among those primarily
|
||||
std::vector<int> const& suggested = c.suggested_pieces();
|
||||
|
||||
p.add_interesting_blocks(suggested, c.get_bitfield()
|
||||
, interesting_pieces, busy_pieces, num_requests
|
||||
, prefer_whole_pieces, c.peer_info_struct(), state
|
||||
, false);
|
||||
}
|
||||
|
||||
// picks the interesting pieces from this peer
|
||||
// the integer is the number of pieces that
|
||||
// should be guaranteed to be available for download
|
||||
|
@ -266,15 +277,18 @@ namespace libtorrent
|
|||
// the last argument is if we should prefer whole pieces
|
||||
// for this peer. If we're downloading one piece in 20 seconds
|
||||
// then use this mode.
|
||||
p.pick_pieces(c.get_bitfield(), interesting_pieces
|
||||
, num_requests, prefer_whole_pieces, c.peer_info_struct()
|
||||
, state, rarest_first);
|
||||
busy_pieces.reserve(10);
|
||||
if (int(interesting_pieces.size()) < num_requests)
|
||||
p.pick_pieces(c.get_bitfield(), interesting_pieces
|
||||
, num_requests, prefer_whole_pieces, c.peer_info_struct()
|
||||
, state, rarest_first);
|
||||
}
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*c.m_logger) << time_now_string() << " PIECE_PICKER [ picked: " << interesting_pieces.size() << " ]\n";
|
||||
(*c.m_logger) << time_now_string() << " PIECE_PICKER [ php: " << prefer_whole_pieces
|
||||
<< " picked: " << interesting_pieces.size() << " ]\n";
|
||||
#endif
|
||||
std::deque<piece_block> const& dq = c.download_queue();
|
||||
std::deque<piece_block> const& rq = c.request_queue();
|
||||
for (std::vector<piece_block>::iterator i = interesting_pieces.begin();
|
||||
i != interesting_pieces.end(); ++i)
|
||||
{
|
||||
|
@ -282,8 +296,6 @@ namespace libtorrent
|
|||
{
|
||||
if (num_requests <= 0) break;
|
||||
// don't request pieces we already have in our request queue
|
||||
const std::deque<piece_block>& dq = c.download_queue();
|
||||
const std::deque<piece_block>& rq = c.request_queue();
|
||||
if (std::find(dq.begin(), dq.end(), *i) != dq.end()
|
||||
|| std::find(rq.begin(), rq.end(), *i) != rq.end())
|
||||
continue;
|
||||
|
@ -516,6 +528,7 @@ namespace libtorrent
|
|||
|
||||
int max_failcount = m_torrent->settings().max_failcount;
|
||||
int min_reconnect_time = m_torrent->settings().min_reconnect_time;
|
||||
bool finished = m_torrent->is_finished();
|
||||
|
||||
aux::session_impl& ses = m_torrent->session();
|
||||
|
||||
|
@ -524,7 +537,7 @@ namespace libtorrent
|
|||
if (i->connection) continue;
|
||||
if (i->banned) continue;
|
||||
if (i->type == peer::not_connectable) continue;
|
||||
if (i->seed && m_torrent->is_seed()) continue;
|
||||
if (i->seed && finished) continue;
|
||||
if (i->failcount >= max_failcount) continue;
|
||||
if (now - i->connected < seconds(i->failcount * min_reconnect_time))
|
||||
continue;
|
||||
|
@ -1179,7 +1192,7 @@ namespace libtorrent
|
|||
&& m_torrent->session().num_uploads() < m_torrent->session().max_uploads()
|
||||
&& (m_torrent->ratio() == 0
|
||||
|| c.share_diff() >= -free_upload_amount
|
||||
|| m_torrent->is_seed()))
|
||||
|| m_torrent->is_finished()))
|
||||
{
|
||||
m_torrent->session().unchoke_peer(c);
|
||||
}
|
||||
|
|
|
@ -181,6 +181,19 @@ namespace libtorrent
|
|||
, bool compact_mode
|
||||
, bool paused
|
||||
, storage_constructor_type sc)
|
||||
{
|
||||
boost::intrusive_ptr<torrent_info> tip(new torrent_info(ti));
|
||||
return m_impl->add_torrent(tip, save_path, resume_data
|
||||
, compact_mode, sc, paused);
|
||||
}
|
||||
|
||||
torrent_handle session::add_torrent(
|
||||
boost::intrusive_ptr<torrent_info> ti
|
||||
, fs::path const& save_path
|
||||
, entry const& resume_data
|
||||
, bool compact_mode
|
||||
, bool paused
|
||||
, storage_constructor_type sc)
|
||||
{
|
||||
return m_impl->add_torrent(ti, save_path, resume_data
|
||||
, compact_mode, sc, paused);
|
||||
|
|
|
@ -786,8 +786,30 @@ namespace detail
|
|||
return;
|
||||
}
|
||||
|
||||
// check if we have any active torrents
|
||||
// if we don't reject the connection
|
||||
if (m_torrents.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool has_active_torrent = false;
|
||||
for (torrent_map::iterator i = m_torrents.begin()
|
||||
, end(m_torrents.end()); i != end; ++i)
|
||||
{
|
||||
if (!i->second->is_paused())
|
||||
{
|
||||
has_active_torrent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!has_active_torrent)
|
||||
return;
|
||||
}
|
||||
|
||||
boost::intrusive_ptr<peer_connection> c(
|
||||
new bt_peer_connection(*this, s, 0));
|
||||
new bt_peer_connection(*this, s, 0));
|
||||
#ifndef NDEBUG
|
||||
c->m_in_constructor = false;
|
||||
#endif
|
||||
|
@ -1454,7 +1476,7 @@ namespace detail
|
|||
}
|
||||
|
||||
torrent_handle session_impl::add_torrent(
|
||||
torrent_info const& ti
|
||||
boost::intrusive_ptr<torrent_info> ti
|
||||
, fs::path const& save_path
|
||||
, entry const& resume_data
|
||||
, bool compact_mode
|
||||
|
@ -1466,7 +1488,7 @@ namespace detail
|
|||
assert(m_external_listen_port > 0);
|
||||
assert(!save_path.empty());
|
||||
|
||||
if (ti.begin_files() == ti.end_files())
|
||||
if (ti->begin_files() == ti->end_files())
|
||||
throw std::runtime_error("no files in torrent");
|
||||
|
||||
// lock the session and the checker thread (the order is important!)
|
||||
|
@ -1479,11 +1501,11 @@ namespace detail
|
|||
throw std::runtime_error("session is closing");
|
||||
|
||||
// is the torrent already active?
|
||||
if (!find_torrent(ti.info_hash()).expired())
|
||||
if (!find_torrent(ti->info_hash()).expired())
|
||||
throw duplicate_torrent();
|
||||
|
||||
// is the torrent currently being checked?
|
||||
if (m_checker_impl.find_torrent(ti.info_hash()))
|
||||
if (m_checker_impl.find_torrent(ti->info_hash()))
|
||||
throw duplicate_torrent();
|
||||
|
||||
// create the torrent and the data associated with
|
||||
|
@ -1508,13 +1530,13 @@ namespace detail
|
|||
new aux::piece_checker_data);
|
||||
d->torrent_ptr = torrent_ptr;
|
||||
d->save_path = save_path;
|
||||
d->info_hash = ti.info_hash();
|
||||
d->info_hash = ti->info_hash();
|
||||
d->resume_data = resume_data;
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
if (m_dht)
|
||||
{
|
||||
torrent_info::nodes_t const& nodes = ti.nodes();
|
||||
torrent_info::nodes_t const& nodes = ti->nodes();
|
||||
std::for_each(nodes.begin(), nodes.end(), bind(
|
||||
(void(dht::dht_tracker::*)(std::pair<std::string, int> const&))
|
||||
&dht::dht_tracker::add_node
|
||||
|
@ -1528,7 +1550,7 @@ namespace detail
|
|||
// job in its queue
|
||||
m_checker_impl.m_cond.notify_one();
|
||||
|
||||
return torrent_handle(this, &m_checker_impl, ti.info_hash());
|
||||
return torrent_handle(this, &m_checker_impl, ti->info_hash());
|
||||
}
|
||||
|
||||
torrent_handle session_impl::add_torrent(
|
||||
|
|
|
@ -345,11 +345,11 @@ namespace libtorrent
|
|||
class storage : public storage_interface, boost::noncopyable
|
||||
{
|
||||
public:
|
||||
storage(torrent_info const& info, fs::path const& path, file_pool& fp)
|
||||
storage(boost::intrusive_ptr<torrent_info const> info, fs::path const& path, file_pool& fp)
|
||||
: m_info(info)
|
||||
, m_files(fp)
|
||||
{
|
||||
assert(info.begin_files(true) != info.end_files(true));
|
||||
assert(info->begin_files(true) != info->end_files(true));
|
||||
m_save_path = fs::complete(path);
|
||||
assert(m_save_path.is_complete());
|
||||
}
|
||||
|
@ -369,11 +369,9 @@ namespace libtorrent
|
|||
size_type read_impl(char* buf, int slot, int offset, int size, bool fill_zero);
|
||||
|
||||
~storage()
|
||||
{
|
||||
m_files.release(this);
|
||||
}
|
||||
{ m_files.release(this); }
|
||||
|
||||
torrent_info const& m_info;
|
||||
boost::intrusive_ptr<torrent_info const> m_info;
|
||||
fs::path m_save_path;
|
||||
// the file pool is typically stored in
|
||||
// the session, to make all storage
|
||||
|
@ -412,8 +410,8 @@ namespace libtorrent
|
|||
{
|
||||
// first, create all missing directories
|
||||
fs::path last_path;
|
||||
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)
|
||||
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();
|
||||
|
||||
|
@ -461,7 +459,7 @@ namespace libtorrent
|
|||
void storage::write_resume_data(entry& rd) const
|
||||
{
|
||||
std::vector<std::pair<size_type, std::time_t> > file_sizes
|
||||
= get_filesizes(m_info, m_save_path);
|
||||
= get_filesizes(*m_info, m_save_path);
|
||||
|
||||
rd["file sizes"] = entry::list_type();
|
||||
entry::list_type& fl = rd["file sizes"].list();
|
||||
|
@ -495,7 +493,7 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
entry::list_type& slots = rd["slots"].list();
|
||||
bool seed = int(slots.size()) == m_info.num_pieces()
|
||||
bool seed = int(slots.size()) == m_info->num_pieces()
|
||||
&& std::find_if(slots.begin(), slots.end()
|
||||
, boost::bind<bool>(std::less<int>()
|
||||
, boost::bind((size_type const& (entry::*)() const)
|
||||
|
@ -510,11 +508,11 @@ namespace libtorrent
|
|||
|
||||
if (seed)
|
||||
{
|
||||
if (m_info.num_files(true) != (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<std::string>(file_sizes.size()) + " actual: "
|
||||
+ boost::lexical_cast<std::string>(m_info.num_files(true)) + ")";
|
||||
+ boost::lexical_cast<std::string>(m_info->num_files(true)) + ")";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -522,8 +520,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(true)
|
||||
, end(m_info.end_files(true)); 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)
|
||||
{
|
||||
|
@ -536,7 +534,7 @@ namespace libtorrent
|
|||
return true;
|
||||
}
|
||||
|
||||
return match_filesizes(m_info, m_save_path, file_sizes
|
||||
return match_filesizes(*m_info, m_save_path, file_sizes
|
||||
, !full_allocation_mode, &error);
|
||||
}
|
||||
|
||||
|
@ -575,11 +573,11 @@ namespace libtorrent
|
|||
m_files.release(this);
|
||||
|
||||
#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION >= 103400
|
||||
old_path = safe_convert((m_save_path / m_info.name()).string());
|
||||
new_path = safe_convert((save_path / m_info.name()).string());
|
||||
old_path = safe_convert((m_save_path / m_info->name()).string());
|
||||
new_path = safe_convert((save_path / m_info->name()).string());
|
||||
#else
|
||||
old_path = m_save_path / m_info.name();
|
||||
new_path = save_path / m_info.name();
|
||||
old_path = m_save_path / m_info->name();
|
||||
new_path = save_path / m_info->name();
|
||||
#endif
|
||||
|
||||
try
|
||||
|
@ -601,7 +599,7 @@ namespace libtorrent
|
|||
/*
|
||||
void storage::shuffle()
|
||||
{
|
||||
int num_pieces = m_info.num_pieces();
|
||||
int num_pieces = m_info->num_pieces();
|
||||
|
||||
std::vector<int> pieces(num_pieces);
|
||||
for (std::vector<int>::iterator i = pieces.begin();
|
||||
|
@ -618,7 +616,7 @@ namespace libtorrent
|
|||
{
|
||||
const int slot_index = targets[i];
|
||||
const int piece_index = pieces[i];
|
||||
const int slot_size =static_cast<int>(m_info.piece_size(slot_index));
|
||||
const int slot_size =static_cast<int>(m_info->piece_size(slot_index));
|
||||
std::vector<char> buf(slot_size);
|
||||
read(&buf[0], piece_index, 0, slot_size);
|
||||
write(&buf[0], slot_index, 0, slot_size);
|
||||
|
@ -629,7 +627,7 @@ namespace libtorrent
|
|||
|
||||
void storage::move_slot(int src_slot, int dst_slot)
|
||||
{
|
||||
int piece_size = m_info.piece_size(dst_slot);
|
||||
int piece_size = m_info->piece_size(dst_slot);
|
||||
m_scratch_buffer.resize(piece_size);
|
||||
read_impl(&m_scratch_buffer[0], src_slot, 0, piece_size, true);
|
||||
write(&m_scratch_buffer[0], dst_slot, 0, piece_size);
|
||||
|
@ -638,9 +636,9 @@ namespace libtorrent
|
|||
void storage::swap_slots(int slot1, int slot2)
|
||||
{
|
||||
// the size of the target slot is the size of the piece
|
||||
int piece_size = m_info.piece_length();
|
||||
int piece1_size = m_info.piece_size(slot2);
|
||||
int piece2_size = m_info.piece_size(slot1);
|
||||
int piece_size = m_info->piece_length();
|
||||
int piece1_size = m_info->piece_size(slot2);
|
||||
int piece2_size = m_info->piece_size(slot1);
|
||||
m_scratch_buffer.resize(piece_size * 2);
|
||||
read_impl(&m_scratch_buffer[0], slot1, 0, piece1_size, true);
|
||||
read_impl(&m_scratch_buffer[piece_size], slot2, 0, piece2_size, true);
|
||||
|
@ -651,10 +649,10 @@ namespace libtorrent
|
|||
void storage::swap_slots3(int slot1, int slot2, int slot3)
|
||||
{
|
||||
// the size of the target slot is the size of the piece
|
||||
int piece_size = m_info.piece_length();
|
||||
int piece1_size = m_info.piece_size(slot2);
|
||||
int piece2_size = m_info.piece_size(slot3);
|
||||
int piece3_size = m_info.piece_size(slot1);
|
||||
int piece_size = m_info->piece_length();
|
||||
int piece1_size = m_info->piece_size(slot2);
|
||||
int piece2_size = m_info->piece_size(slot3);
|
||||
int piece3_size = m_info->piece_size(slot1);
|
||||
m_scratch_buffer.resize(piece_size * 2);
|
||||
read_impl(&m_scratch_buffer[0], slot1, 0, piece1_size, true);
|
||||
read_impl(&m_scratch_buffer[piece_size], slot2, 0, piece2_size, true);
|
||||
|
@ -681,25 +679,25 @@ namespace libtorrent
|
|||
, bool fill_zero)
|
||||
{
|
||||
assert(buf != 0);
|
||||
assert(slot >= 0 && slot < m_info.num_pieces());
|
||||
assert(slot >= 0 && slot < m_info->num_pieces());
|
||||
assert(offset >= 0);
|
||||
assert(offset < m_info.piece_size(slot));
|
||||
assert(offset < m_info->piece_size(slot));
|
||||
assert(size > 0);
|
||||
|
||||
#ifndef NDEBUG
|
||||
std::vector<file_slice> slices
|
||||
= m_info.map_block(slot, offset, size, true);
|
||||
= m_info->map_block(slot, offset, size, true);
|
||||
assert(!slices.empty());
|
||||
#endif
|
||||
|
||||
size_type start = slot * (size_type)m_info.piece_length() + offset;
|
||||
assert(start + size <= m_info.total_size());
|
||||
size_type start = slot * (size_type)m_info->piece_length() + offset;
|
||||
assert(start + size <= m_info->total_size());
|
||||
|
||||
// find the file iterator and file offset
|
||||
size_type file_offset = start;
|
||||
std::vector<file_entry>::const_iterator file_iter;
|
||||
|
||||
for (file_iter = m_info.begin_files(true);;)
|
||||
for (file_iter = m_info->begin_files(true);;)
|
||||
{
|
||||
if (file_offset < file_iter->size)
|
||||
break;
|
||||
|
@ -732,7 +730,7 @@ namespace libtorrent
|
|||
#endif
|
||||
|
||||
int left_to_read = size;
|
||||
int slot_size = static_cast<int>(m_info.piece_size(slot));
|
||||
int slot_size = static_cast<int>(m_info->piece_size(slot));
|
||||
|
||||
if (offset + left_to_read > slot_size)
|
||||
left_to_read = slot_size - offset;
|
||||
|
@ -757,7 +755,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, true).path
|
||||
assert(m_info->file_at(slices[counter].file_index, true).path
|
||||
== file_iter->path);
|
||||
#endif
|
||||
|
||||
|
@ -807,30 +805,30 @@ namespace libtorrent
|
|||
{
|
||||
assert(buf != 0);
|
||||
assert(slot >= 0);
|
||||
assert(slot < m_info.num_pieces());
|
||||
assert(slot < m_info->num_pieces());
|
||||
assert(offset >= 0);
|
||||
assert(size > 0);
|
||||
|
||||
#ifndef NDEBUG
|
||||
std::vector<file_slice> slices
|
||||
= m_info.map_block(slot, offset, size, true);
|
||||
= m_info->map_block(slot, offset, size, true);
|
||||
assert(!slices.empty());
|
||||
#endif
|
||||
|
||||
size_type start = slot * (size_type)m_info.piece_length() + offset;
|
||||
size_type start = slot * (size_type)m_info->piece_length() + offset;
|
||||
|
||||
// find the file iterator and file offset
|
||||
size_type file_offset = start;
|
||||
std::vector<file_entry>::const_iterator file_iter;
|
||||
|
||||
for (file_iter = m_info.begin_files(true);;)
|
||||
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(true));
|
||||
assert(file_iter != m_info->end_files(true));
|
||||
}
|
||||
|
||||
fs::path p(m_save_path / file_iter->path);
|
||||
|
@ -850,7 +848,7 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
int left_to_write = size;
|
||||
int slot_size = static_cast<int>(m_info.piece_size(slot));
|
||||
int slot_size = static_cast<int>(m_info->piece_size(slot));
|
||||
|
||||
if (offset + left_to_write > slot_size)
|
||||
left_to_write = slot_size - offset;
|
||||
|
@ -874,7 +872,7 @@ namespace libtorrent
|
|||
{
|
||||
assert(int(slices.size()) > counter);
|
||||
assert(slices[counter].size == write_bytes);
|
||||
assert(m_info.file_at(slices[counter].file_index, true).path
|
||||
assert(m_info->file_at(slices[counter].file_index, true).path
|
||||
== file_iter->path);
|
||||
|
||||
assert(buf_pos >= 0);
|
||||
|
@ -902,7 +900,7 @@ namespace libtorrent
|
|||
#endif
|
||||
++file_iter;
|
||||
|
||||
assert(file_iter != m_info.end_files(true));
|
||||
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(
|
||||
|
@ -913,7 +911,7 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
storage_interface* default_storage_constructor(torrent_info const& ti
|
||||
storage_interface* default_storage_constructor(boost::intrusive_ptr<torrent_info const> ti
|
||||
, fs::path const& path, file_pool& fp)
|
||||
{
|
||||
return new storage(ti, path, fp);
|
||||
|
@ -1027,7 +1025,7 @@ namespace libtorrent
|
|||
|
||||
piece_manager::piece_manager(
|
||||
boost::shared_ptr<void> const& torrent
|
||||
, torrent_info const& ti
|
||||
, boost::intrusive_ptr<torrent_info const> ti
|
||||
, fs::path const& save_path
|
||||
, file_pool& fp
|
||||
, disk_io_thread& io
|
||||
|
@ -1037,7 +1035,7 @@ namespace libtorrent
|
|||
, m_fill_mode(true)
|
||||
, m_info(ti)
|
||||
, m_save_path(complete(save_path))
|
||||
, m_allocating(false)
|
||||
, m_storage_constructor(sc)
|
||||
, m_io_thread(io)
|
||||
, m_torrent(torrent)
|
||||
{
|
||||
|
@ -1140,7 +1138,7 @@ namespace libtorrent
|
|||
|
||||
int slot = m_piece_to_slot[piece];
|
||||
assert(slot != has_no_slot);
|
||||
return m_storage->hash_for_slot(slot, ph, m_info.piece_size(piece));
|
||||
return m_storage->hash_for_slot(slot, ph, m_info->piece_size(piece));
|
||||
}
|
||||
|
||||
void piece_manager::release_files_impl()
|
||||
|
@ -1200,7 +1198,7 @@ namespace libtorrent
|
|||
|
||||
int piece_manager::slot_for_piece(int piece_index) const
|
||||
{
|
||||
assert(piece_index >= 0 && piece_index < m_info.num_pieces());
|
||||
assert(piece_index >= 0 && piece_index < m_info->num_pieces());
|
||||
return m_piece_to_slot[piece_index];
|
||||
}
|
||||
|
||||
|
@ -1211,13 +1209,13 @@ namespace libtorrent
|
|||
try
|
||||
{
|
||||
assert(slot_index >= 0);
|
||||
assert(slot_index < m_info.num_pieces());
|
||||
assert(slot_index < m_info->num_pieces());
|
||||
assert(block_size > 0);
|
||||
|
||||
adler32_crc crc;
|
||||
std::vector<char> buf(block_size);
|
||||
int num_blocks = static_cast<int>(m_info.piece_size(slot_index)) / block_size;
|
||||
int last_block_size = static_cast<int>(m_info.piece_size(slot_index)) % block_size;
|
||||
int num_blocks = static_cast<int>(m_info->piece_size(slot_index)) / block_size;
|
||||
int last_block_size = static_cast<int>(m_info->piece_size(slot_index)) % block_size;
|
||||
if (last_block_size == 0) last_block_size = block_size;
|
||||
|
||||
for (int i = 0; i < num_blocks-1; ++i)
|
||||
|
@ -1310,11 +1308,11 @@ namespace libtorrent
|
|||
{
|
||||
// INVARIANT_CHECK;
|
||||
|
||||
assert((int)have_pieces.size() == m_info.num_pieces());
|
||||
assert((int)have_pieces.size() == m_info->num_pieces());
|
||||
|
||||
const int piece_size = static_cast<int>(m_info.piece_length());
|
||||
const int last_piece_size = static_cast<int>(m_info.piece_size(
|
||||
m_info.num_pieces() - 1));
|
||||
const int piece_size = static_cast<int>(m_info->piece_length());
|
||||
const int last_piece_size = static_cast<int>(m_info->piece_size(
|
||||
m_info->num_pieces() - 1));
|
||||
|
||||
assert((int)piece_data.size() >= last_piece_size);
|
||||
|
||||
|
@ -1470,7 +1468,7 @@ namespace libtorrent
|
|||
|
||||
INVARIANT_CHECK;
|
||||
|
||||
assert(m_info.piece_length() > 0);
|
||||
assert(m_info->piece_length() > 0);
|
||||
|
||||
m_compact_mode = compact_mode;
|
||||
|
||||
|
@ -1480,13 +1478,13 @@ namespace libtorrent
|
|||
// by check_pieces.
|
||||
// m_storage->shuffle();
|
||||
|
||||
m_piece_to_slot.resize(m_info.num_pieces(), has_no_slot);
|
||||
m_slot_to_piece.resize(m_info.num_pieces(), unallocated);
|
||||
m_piece_to_slot.resize(m_info->num_pieces(), has_no_slot);
|
||||
m_slot_to_piece.resize(m_info->num_pieces(), unallocated);
|
||||
m_free_slots.clear();
|
||||
m_unallocated_slots.clear();
|
||||
|
||||
pieces.clear();
|
||||
pieces.resize(m_info.num_pieces(), false);
|
||||
pieces.resize(m_info->num_pieces(), false);
|
||||
num_pieces = 0;
|
||||
|
||||
// if we have fast-resume info
|
||||
|
@ -1591,7 +1589,7 @@ namespace libtorrent
|
|||
return std::make_pair(false, 1.f);
|
||||
}
|
||||
|
||||
if (int(m_unallocated_slots.size()) == m_info.num_pieces()
|
||||
if (int(m_unallocated_slots.size()) == m_info->num_pieces()
|
||||
&& !m_fill_mode)
|
||||
{
|
||||
// if there is not a single file on disk, just
|
||||
|
@ -1633,8 +1631,8 @@ namespace libtorrent
|
|||
assert(!m_fill_mode);
|
||||
std::vector<int>().swap(m_unallocated_slots);
|
||||
std::fill(m_slot_to_piece.begin(), m_slot_to_piece.end(), int(unassigned));
|
||||
m_free_slots.resize(m_info.num_pieces());
|
||||
for (int i = 0; i < m_info.num_pieces(); ++i)
|
||||
m_free_slots.resize(m_info->num_pieces());
|
||||
for (int i = 0; i < m_info->num_pieces(); ++i)
|
||||
m_free_slots[i] = i;
|
||||
}
|
||||
|
||||
|
@ -1654,15 +1652,15 @@ namespace libtorrent
|
|||
if (m_hash_to_piece.empty())
|
||||
{
|
||||
m_current_slot = 0;
|
||||
for (int i = 0; i < m_info.num_pieces(); ++i)
|
||||
for (int i = 0; i < m_info->num_pieces(); ++i)
|
||||
{
|
||||
m_hash_to_piece.insert(std::make_pair(m_info.hash_for_piece(i), i));
|
||||
m_hash_to_piece.insert(std::make_pair(m_info->hash_for_piece(i), i));
|
||||
}
|
||||
std::fill(pieces.begin(), pieces.end(), false);
|
||||
}
|
||||
|
||||
m_piece_data.resize(int(m_info.piece_length()));
|
||||
int piece_size = int(m_info.piece_size(m_current_slot));
|
||||
m_piece_data.resize(int(m_info->piece_length()));
|
||||
int piece_size = int(m_info->piece_size(m_current_slot));
|
||||
int num_read = m_storage->read(&m_piece_data[0]
|
||||
, m_current_slot, 0, piece_size);
|
||||
|
||||
|
@ -1865,9 +1863,9 @@ 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(true);
|
||||
i != m_info.end_files(true); ++i)
|
||||
size_type current_offset = m_current_slot * m_info->piece_length();
|
||||
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;
|
||||
|
@ -1875,8 +1873,8 @@ namespace libtorrent
|
|||
|
||||
assert(file_offset > current_offset);
|
||||
int skip_blocks = static_cast<int>(
|
||||
(file_offset - current_offset + m_info.piece_length() - 1)
|
||||
/ m_info.piece_length());
|
||||
(file_offset - current_offset + m_info->piece_length() - 1)
|
||||
/ m_info->piece_length());
|
||||
|
||||
for (int i = m_current_slot; i < m_current_slot + skip_blocks; ++i)
|
||||
{
|
||||
|
@ -1889,9 +1887,9 @@ namespace libtorrent
|
|||
}
|
||||
++m_current_slot;
|
||||
|
||||
if (m_current_slot >= m_info.num_pieces())
|
||||
if (m_current_slot >= m_info->num_pieces())
|
||||
{
|
||||
assert(m_current_slot == m_info.num_pieces());
|
||||
assert(m_current_slot == m_info->num_pieces());
|
||||
|
||||
// clear the memory we've been using
|
||||
std::vector<char>().swap(m_piece_data);
|
||||
|
@ -1903,7 +1901,7 @@ namespace libtorrent
|
|||
|
||||
assert(num_pieces == std::count(pieces.begin(), pieces.end(), true));
|
||||
|
||||
return std::make_pair(false, (float)m_current_slot / m_info.num_pieces());
|
||||
return std::make_pair(false, (float)m_current_slot / m_info->num_pieces());
|
||||
}
|
||||
|
||||
int piece_manager::allocate_slot_for_piece(int piece_index)
|
||||
|
@ -1945,7 +1943,7 @@ namespace libtorrent
|
|||
|
||||
// special case to make sure we don't use the last slot
|
||||
// when we shouldn't, since it's smaller than ordinary slots
|
||||
if (*iter == m_info.num_pieces() - 1 && piece_index != *iter)
|
||||
if (*iter == m_info->num_pieces() - 1 && piece_index != *iter)
|
||||
{
|
||||
if (m_free_slots.size() == 1)
|
||||
allocate_slots(1);
|
||||
|
@ -2050,7 +2048,7 @@ namespace libtorrent
|
|||
}
|
||||
else if (m_fill_mode)
|
||||
{
|
||||
int piece_size = int(m_info.piece_size(pos));
|
||||
int piece_size = int(m_info->piece_size(pos));
|
||||
int offset = 0;
|
||||
for (; piece_size > 0; piece_size -= stack_buffer_size
|
||||
, offset += stack_buffer_size)
|
||||
|
@ -2076,8 +2074,8 @@ namespace libtorrent
|
|||
boost::recursive_mutex::scoped_lock lock(m_mutex);
|
||||
if (m_piece_to_slot.empty()) return;
|
||||
|
||||
assert((int)m_piece_to_slot.size() == m_info.num_pieces());
|
||||
assert((int)m_slot_to_piece.size() == m_info.num_pieces());
|
||||
assert((int)m_piece_to_slot.size() == m_info->num_pieces());
|
||||
assert((int)m_slot_to_piece.size() == m_info->num_pieces());
|
||||
|
||||
for (std::vector<int>::const_iterator i = m_free_slots.begin();
|
||||
i != m_free_slots.end(); ++i)
|
||||
|
@ -2099,7 +2097,7 @@ namespace libtorrent
|
|||
== m_unallocated_slots.end());
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_info.num_pieces(); ++i)
|
||||
for (int i = 0; i < m_info->num_pieces(); ++i)
|
||||
{
|
||||
// Check domain of piece_to_slot's elements
|
||||
if (m_piece_to_slot[i] != has_no_slot)
|
||||
|
@ -2187,7 +2185,7 @@ namespace libtorrent
|
|||
|
||||
s << "index\tslot\tpiece\n";
|
||||
|
||||
for (int i = 0; i < m_info.num_pieces(); ++i)
|
||||
for (int i = 0; i < m_info->num_pieces(); ++i)
|
||||
{
|
||||
s << i << "\t" << m_slot_to_piece[i] << "\t";
|
||||
s << m_piece_to_slot[i] << "\n";
|
||||
|
|
|
@ -150,7 +150,7 @@ namespace libtorrent
|
|||
torrent::torrent(
|
||||
session_impl& ses
|
||||
, aux::checker_impl& checker
|
||||
, torrent_info const& tf
|
||||
, boost::intrusive_ptr<torrent_info> tf
|
||||
, fs::path const& save_path
|
||||
, tcp::endpoint const& net_interface
|
||||
, bool compact_mode
|
||||
|
@ -181,7 +181,7 @@ namespace libtorrent
|
|||
, m_ses(ses)
|
||||
, m_checker(checker)
|
||||
, m_picker(0)
|
||||
, m_trackers(m_torrent_file.trackers())
|
||||
, m_trackers(m_torrent_file->trackers())
|
||||
, m_last_working_tracker(-1)
|
||||
, m_currently_trying_tracker(0)
|
||||
, m_failed_trackers(0)
|
||||
|
@ -221,7 +221,7 @@ namespace libtorrent
|
|||
, int block_size
|
||||
, storage_constructor_type sc
|
||||
, bool paused)
|
||||
: m_torrent_file(info_hash)
|
||||
: m_torrent_file(new torrent_info(info_hash))
|
||||
, m_abort(false)
|
||||
, m_paused(paused)
|
||||
, m_just_paused(false)
|
||||
|
@ -277,7 +277,7 @@ namespace libtorrent
|
|||
if (tracker_url)
|
||||
{
|
||||
m_trackers.push_back(announce_entry(tracker_url));
|
||||
m_torrent_file.add_tracker(tracker_url);
|
||||
m_torrent_file->add_tracker(tracker_url);
|
||||
}
|
||||
|
||||
m_policy.reset(new policy(this));
|
||||
|
@ -286,7 +286,7 @@ namespace libtorrent
|
|||
void torrent::start()
|
||||
{
|
||||
boost::weak_ptr<torrent> self(shared_from_this());
|
||||
if (m_torrent_file.is_valid()) init();
|
||||
if (m_torrent_file->is_valid()) init();
|
||||
m_announce_timer.expires_from_now(seconds(1));
|
||||
m_announce_timer.async_wait(m_ses.m_strand.wrap(
|
||||
bind(&torrent::on_announce_disp, self, _1)));
|
||||
|
@ -296,7 +296,7 @@ namespace libtorrent
|
|||
bool torrent::should_announce_dht() const
|
||||
{
|
||||
// don't announce private torrents
|
||||
if (m_torrent_file.is_valid() && m_torrent_file.priv()) return false;
|
||||
if (m_torrent_file->is_valid() && m_torrent_file->priv()) return false;
|
||||
|
||||
if (m_trackers.empty()) return true;
|
||||
|
||||
|
@ -334,7 +334,7 @@ namespace libtorrent
|
|||
|
||||
std::string torrent::name() const
|
||||
{
|
||||
if (valid_metadata()) return m_torrent_file.name();
|
||||
if (valid_metadata()) return m_torrent_file->name();
|
||||
if (m_name) return *m_name;
|
||||
return "";
|
||||
}
|
||||
|
@ -350,22 +350,22 @@ namespace libtorrent
|
|||
// shared_from_this()
|
||||
void torrent::init()
|
||||
{
|
||||
assert(m_torrent_file.is_valid());
|
||||
assert(m_torrent_file.num_files() > 0);
|
||||
assert(m_torrent_file.total_size() >= 0);
|
||||
assert(m_torrent_file->is_valid());
|
||||
assert(m_torrent_file->num_files() > 0);
|
||||
assert(m_torrent_file->total_size() >= 0);
|
||||
|
||||
m_have_pieces.resize(m_torrent_file.num_pieces(), false);
|
||||
m_have_pieces.resize(m_torrent_file->num_pieces(), false);
|
||||
// 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
|
||||
, m_save_path, m_ses.m_files, m_ses.m_disk_thread, m_storage_constructor);
|
||||
m_storage = m_owning_storage.get();
|
||||
m_block_size = calculate_block_size(m_torrent_file, m_default_block_size);
|
||||
m_block_size = calculate_block_size(*m_torrent_file, m_default_block_size);
|
||||
m_picker.reset(new piece_picker(
|
||||
static_cast<int>(m_torrent_file.piece_length() / m_block_size)
|
||||
, static_cast<int>((m_torrent_file.total_size()+m_block_size-1)/m_block_size)));
|
||||
static_cast<int>(m_torrent_file->piece_length() / m_block_size)
|
||||
, static_cast<int>((m_torrent_file->total_size()+m_block_size-1)/m_block_size)));
|
||||
|
||||
std::vector<std::string> const& url_seeds = m_torrent_file.url_seeds();
|
||||
std::vector<std::string> const& url_seeds = m_torrent_file->url_seeds();
|
||||
std::copy(url_seeds.begin(), url_seeds.end(), std::inserter(m_web_seeds
|
||||
, m_web_seeds.begin()));
|
||||
}
|
||||
|
@ -393,7 +393,7 @@ namespace libtorrent
|
|||
{
|
||||
boost::weak_ptr<torrent> self(shared_from_this());
|
||||
|
||||
if (!m_torrent_file.priv())
|
||||
if (!m_torrent_file->priv())
|
||||
{
|
||||
// announce on local network every 5 minutes
|
||||
m_announce_timer.expires_from_now(minutes(5));
|
||||
|
@ -401,7 +401,7 @@ namespace libtorrent
|
|||
bind(&torrent::on_announce_disp, self, _1)));
|
||||
|
||||
// announce with the local discovery service
|
||||
m_ses.announce_lsd(m_torrent_file.info_hash());
|
||||
m_ses.announce_lsd(m_torrent_file->info_hash());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -419,7 +419,7 @@ namespace libtorrent
|
|||
// TODO: There should be a way to abort an announce operation on the dht.
|
||||
// when the torrent is destructed
|
||||
assert(m_ses.m_external_listen_port > 0);
|
||||
m_ses.m_dht->announce(m_torrent_file.info_hash()
|
||||
m_ses.m_dht->announce(m_torrent_file->info_hash()
|
||||
, m_ses.m_external_listen_port
|
||||
, m_ses.m_strand.wrap(bind(&torrent::on_dht_announce_response_disp, self, _1)));
|
||||
}
|
||||
|
@ -465,7 +465,7 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_torrent_file.trackers().empty()) return false;
|
||||
if (m_torrent_file->trackers().empty()) return false;
|
||||
|
||||
if (m_just_paused)
|
||||
{
|
||||
|
@ -615,7 +615,7 @@ namespace libtorrent
|
|||
// if we don't have the metadata yet, we
|
||||
// cannot tell how big the torrent is.
|
||||
if (!valid_metadata()) return -1;
|
||||
return m_torrent_file.total_size()
|
||||
return m_torrent_file->total_size()
|
||||
- quantized_bytes_done();
|
||||
}
|
||||
|
||||
|
@ -625,23 +625,23 @@ namespace libtorrent
|
|||
|
||||
if (!valid_metadata()) return 0;
|
||||
|
||||
if (m_torrent_file.num_pieces() == 0)
|
||||
if (m_torrent_file->num_pieces() == 0)
|
||||
return 0;
|
||||
|
||||
if (is_seed()) return m_torrent_file.total_size();
|
||||
if (is_seed()) return m_torrent_file->total_size();
|
||||
|
||||
const int last_piece = m_torrent_file.num_pieces() - 1;
|
||||
const int last_piece = m_torrent_file->num_pieces() - 1;
|
||||
|
||||
size_type total_done
|
||||
= m_num_pieces * m_torrent_file.piece_length();
|
||||
= m_num_pieces * m_torrent_file->piece_length();
|
||||
|
||||
// if we have the last piece, we have to correct
|
||||
// the amount we have, since the first calculation
|
||||
// assumed all pieces were of equal size
|
||||
if (m_have_pieces[last_piece])
|
||||
{
|
||||
int corr = m_torrent_file.piece_size(last_piece)
|
||||
- m_torrent_file.piece_length();
|
||||
int corr = m_torrent_file->piece_size(last_piece)
|
||||
- m_torrent_file->piece_length();
|
||||
total_done += corr;
|
||||
}
|
||||
return total_done;
|
||||
|
@ -654,42 +654,42 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (!valid_metadata() || m_torrent_file.num_pieces() == 0)
|
||||
if (!valid_metadata() || m_torrent_file->num_pieces() == 0)
|
||||
return tuple<size_type, size_type>(0,0);
|
||||
|
||||
const int last_piece = m_torrent_file.num_pieces() - 1;
|
||||
const int last_piece = m_torrent_file->num_pieces() - 1;
|
||||
|
||||
if (is_seed())
|
||||
return make_tuple(m_torrent_file.total_size()
|
||||
, m_torrent_file.total_size());
|
||||
return make_tuple(m_torrent_file->total_size()
|
||||
, m_torrent_file->total_size());
|
||||
|
||||
size_type wanted_done = (m_num_pieces - m_picker->num_have_filtered())
|
||||
* m_torrent_file.piece_length();
|
||||
* m_torrent_file->piece_length();
|
||||
|
||||
size_type total_done
|
||||
= m_num_pieces * m_torrent_file.piece_length();
|
||||
assert(m_num_pieces < m_torrent_file.num_pieces());
|
||||
= m_num_pieces * m_torrent_file->piece_length();
|
||||
assert(m_num_pieces < m_torrent_file->num_pieces());
|
||||
|
||||
// if we have the last piece, we have to correct
|
||||
// the amount we have, since the first calculation
|
||||
// assumed all pieces were of equal size
|
||||
if (m_have_pieces[last_piece])
|
||||
{
|
||||
int corr = m_torrent_file.piece_size(last_piece)
|
||||
- m_torrent_file.piece_length();
|
||||
int corr = m_torrent_file->piece_size(last_piece)
|
||||
- m_torrent_file->piece_length();
|
||||
total_done += corr;
|
||||
if (m_picker->piece_priority(last_piece) != 0)
|
||||
wanted_done += corr;
|
||||
}
|
||||
|
||||
assert(total_done <= m_torrent_file.total_size());
|
||||
assert(wanted_done <= m_torrent_file.total_size());
|
||||
assert(total_done <= m_torrent_file->total_size());
|
||||
assert(wanted_done <= m_torrent_file->total_size());
|
||||
|
||||
const std::vector<piece_picker::downloading_piece>& dl_queue
|
||||
= m_picker->get_download_queue();
|
||||
|
||||
const int blocks_per_piece = static_cast<int>(
|
||||
m_torrent_file.piece_length() / m_block_size);
|
||||
m_torrent_file->piece_length() / m_block_size);
|
||||
|
||||
for (std::vector<piece_picker::downloading_piece>::const_iterator i =
|
||||
dl_queue.begin(); i != dl_queue.end(); ++i)
|
||||
|
@ -722,15 +722,15 @@ namespace libtorrent
|
|||
== piece_picker::block_info::state_finished)
|
||||
{
|
||||
corr -= m_block_size;
|
||||
corr += m_torrent_file.piece_size(last_piece) % m_block_size;
|
||||
corr += m_torrent_file->piece_size(last_piece) % m_block_size;
|
||||
}
|
||||
total_done += corr;
|
||||
if (m_picker->piece_priority(index) != 0)
|
||||
wanted_done += corr;
|
||||
}
|
||||
|
||||
assert(total_done <= m_torrent_file.total_size());
|
||||
assert(wanted_done <= m_torrent_file.total_size());
|
||||
assert(total_done <= m_torrent_file->total_size());
|
||||
assert(wanted_done <= m_torrent_file->total_size());
|
||||
|
||||
std::map<piece_block, int> downloading_piece;
|
||||
for (const_peer_iterator i = begin(); i != end(); ++i)
|
||||
|
@ -760,10 +760,10 @@ namespace libtorrent
|
|||
}
|
||||
#ifndef NDEBUG
|
||||
assert(p->bytes_downloaded <= p->full_block_bytes);
|
||||
int last_piece = m_torrent_file.num_pieces() - 1;
|
||||
int last_piece = m_torrent_file->num_pieces() - 1;
|
||||
if (p->piece_index == last_piece
|
||||
&& p->block_index == m_torrent_file.piece_size(last_piece) / block_size())
|
||||
assert(p->full_block_bytes == m_torrent_file.piece_size(last_piece) % block_size());
|
||||
&& p->block_index == m_torrent_file->piece_size(last_piece) / block_size())
|
||||
assert(p->full_block_bytes == m_torrent_file->piece_size(last_piece) % block_size());
|
||||
else
|
||||
assert(p->full_block_bytes == block_size());
|
||||
#endif
|
||||
|
@ -779,7 +779,7 @@ namespace libtorrent
|
|||
|
||||
#ifndef NDEBUG
|
||||
|
||||
if (total_done >= m_torrent_file.total_size())
|
||||
if (total_done >= m_torrent_file->total_size())
|
||||
{
|
||||
std::copy(m_have_pieces.begin(), m_have_pieces.end()
|
||||
, std::ostream_iterator<bool>(std::cerr, " "));
|
||||
|
@ -810,8 +810,8 @@ namespace libtorrent
|
|||
|
||||
}
|
||||
|
||||
assert(total_done <= m_torrent_file.total_size());
|
||||
assert(wanted_done <= m_torrent_file.total_size());
|
||||
assert(total_done <= m_torrent_file->total_size());
|
||||
assert(wanted_done <= m_torrent_file->total_size());
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -908,14 +908,14 @@ namespace libtorrent
|
|||
// think that it has received all of it until this function
|
||||
// resets the download queue. So, we cannot do the
|
||||
// invariant check here since it assumes:
|
||||
// (total_done == m_torrent_file.total_size()) => is_seed()
|
||||
// (total_done == m_torrent_file->total_size()) => is_seed()
|
||||
// INVARIANT_CHECK;
|
||||
|
||||
assert(m_storage);
|
||||
assert(m_storage->refcount() > 0);
|
||||
assert(m_picker.get());
|
||||
assert(index >= 0);
|
||||
assert(index < m_torrent_file.num_pieces());
|
||||
assert(index < m_torrent_file->num_pieces());
|
||||
|
||||
if (m_ses.m_alerts.should_post(alert::info))
|
||||
{
|
||||
|
@ -924,7 +924,7 @@ namespace libtorrent
|
|||
m_ses.m_alerts.post_alert(hash_failed_alert(get_handle(), index, s.str()));
|
||||
}
|
||||
// increase the total amount of failed bytes
|
||||
m_total_failed_bytes += m_torrent_file.piece_size(index);
|
||||
m_total_failed_bytes += m_torrent_file->piece_size(index);
|
||||
|
||||
std::vector<void*> downloaders;
|
||||
m_picker->get_downloaders(downloaders, index);
|
||||
|
@ -1047,7 +1047,7 @@ namespace libtorrent
|
|||
// INVARIANT_CHECK;
|
||||
|
||||
assert(index >= 0);
|
||||
assert(index < m_torrent_file.num_pieces());
|
||||
assert(index < m_torrent_file->num_pieces());
|
||||
|
||||
std::vector<void*> downloaders;
|
||||
m_picker->get_downloaders(downloaders, index);
|
||||
|
@ -1090,7 +1090,7 @@ namespace libtorrent
|
|||
if (is_seed())
|
||||
{
|
||||
m_picker.reset();
|
||||
m_torrent_file.seed_free();
|
||||
m_torrent_file->seed_free();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1124,7 +1124,7 @@ namespace libtorrent
|
|||
// this call is only valid on torrents with metadata
|
||||
assert(m_picker.get());
|
||||
assert(index >= 0);
|
||||
assert(index < m_torrent_file.num_pieces());
|
||||
assert(index < m_torrent_file->num_pieces());
|
||||
|
||||
bool filter_updated = m_picker->set_piece_priority(index, priority);
|
||||
if (filter_updated) update_peer_interest();
|
||||
|
@ -1140,7 +1140,7 @@ namespace libtorrent
|
|||
// this call is only valid on torrents with metadata
|
||||
assert(m_picker.get());
|
||||
assert(index >= 0);
|
||||
assert(index < m_torrent_file.num_pieces());
|
||||
assert(index < m_torrent_file->num_pieces());
|
||||
|
||||
return m_picker->piece_priority(index);
|
||||
}
|
||||
|
@ -1176,7 +1176,7 @@ namespace libtorrent
|
|||
if (is_seed())
|
||||
{
|
||||
pieces.clear();
|
||||
pieces.resize(m_torrent_file.num_pieces(), 1);
|
||||
pieces.resize(m_torrent_file->num_pieces(), 1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1201,20 +1201,20 @@ namespace libtorrent
|
|||
|
||||
// the bitmask need to have exactly one bit for every file
|
||||
// in the torrent
|
||||
assert(int(files.size()) == m_torrent_file.num_files());
|
||||
assert(int(files.size()) == m_torrent_file->num_files());
|
||||
|
||||
size_type position = 0;
|
||||
|
||||
if (m_torrent_file.num_pieces() == 0) return;
|
||||
if (m_torrent_file->num_pieces() == 0) return;
|
||||
|
||||
int piece_length = m_torrent_file.piece_length();
|
||||
int piece_length = m_torrent_file->piece_length();
|
||||
// initialize the piece priorities to 0, then only allow
|
||||
// setting higher priorities
|
||||
std::vector<int> pieces(m_torrent_file.num_pieces(), 0);
|
||||
std::vector<int> pieces(m_torrent_file->num_pieces(), 0);
|
||||
for (int i = 0; i < int(files.size()); ++i)
|
||||
{
|
||||
size_type start = position;
|
||||
size_type size = m_torrent_file.file_at(i).size;
|
||||
size_type size = m_torrent_file->file_at(i).size;
|
||||
if (size == 0) continue;
|
||||
position += size;
|
||||
// mark all pieces of the file with this file's priority
|
||||
|
@ -1250,7 +1250,7 @@ namespace libtorrent
|
|||
// this call is only valid on torrents with metadata
|
||||
assert(m_picker.get());
|
||||
assert(index >= 0);
|
||||
assert(index < m_torrent_file.num_pieces());
|
||||
assert(index < m_torrent_file->num_pieces());
|
||||
|
||||
m_picker->set_piece_priority(index, filter ? 1 : 0);
|
||||
update_peer_interest();
|
||||
|
@ -1287,7 +1287,7 @@ namespace libtorrent
|
|||
|
||||
assert(m_picker.get());
|
||||
assert(index >= 0);
|
||||
assert(index < m_torrent_file.num_pieces());
|
||||
assert(index < m_torrent_file->num_pieces());
|
||||
|
||||
return m_picker->piece_priority(index) == 0;
|
||||
}
|
||||
|
@ -1301,7 +1301,7 @@ namespace libtorrent
|
|||
if (is_seed())
|
||||
{
|
||||
bitmask.clear();
|
||||
bitmask.resize(m_torrent_file.num_pieces(), false);
|
||||
bitmask.resize(m_torrent_file->num_pieces(), false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1318,20 +1318,20 @@ namespace libtorrent
|
|||
|
||||
// the bitmask need to have exactly one bit for every file
|
||||
// in the torrent
|
||||
assert((int)bitmask.size() == m_torrent_file.num_files());
|
||||
assert((int)bitmask.size() == m_torrent_file->num_files());
|
||||
|
||||
size_type position = 0;
|
||||
|
||||
if (m_torrent_file.num_pieces())
|
||||
if (m_torrent_file->num_pieces())
|
||||
{
|
||||
int piece_length = m_torrent_file.piece_length();
|
||||
int piece_length = m_torrent_file->piece_length();
|
||||
// mark all pieces as filtered, then clear the bits for files
|
||||
// that should be downloaded
|
||||
std::vector<bool> piece_filter(m_torrent_file.num_pieces(), true);
|
||||
std::vector<bool> piece_filter(m_torrent_file->num_pieces(), true);
|
||||
for (int i = 0; i < (int)bitmask.size(); ++i)
|
||||
{
|
||||
size_type start = position;
|
||||
position += m_torrent_file.file_at(i).size;
|
||||
position += m_torrent_file->file_at(i).size;
|
||||
// is the file selected for download?
|
||||
if (!bitmask[i])
|
||||
{
|
||||
|
@ -1366,7 +1366,7 @@ namespace libtorrent
|
|||
m_next_request = time_now() + seconds(tracker_retry_delay_max);
|
||||
|
||||
tracker_request req;
|
||||
req.info_hash = m_torrent_file.info_hash();
|
||||
req.info_hash = m_torrent_file->info_hash();
|
||||
req.pid = m_ses.get_peer_id();
|
||||
req.downloaded = m_stat.total_payload_download();
|
||||
req.uploaded = m_stat.total_payload_upload();
|
||||
|
@ -1890,8 +1890,8 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
assert(!m_torrent_file.is_valid());
|
||||
m_torrent_file.parse_info_section(metadata);
|
||||
assert(!m_torrent_file->is_valid());
|
||||
m_torrent_file->parse_info_section(metadata);
|
||||
|
||||
init();
|
||||
|
||||
|
@ -1901,12 +1901,12 @@ namespace libtorrent
|
|||
new aux::piece_checker_data);
|
||||
d->torrent_ptr = shared_from_this();
|
||||
d->save_path = m_save_path;
|
||||
d->info_hash = m_torrent_file.info_hash();
|
||||
d->info_hash = m_torrent_file->info_hash();
|
||||
// add the torrent to the queue to be checked
|
||||
m_checker.m_torrents.push_back(d);
|
||||
typedef session_impl::torrent_map torrent_map;
|
||||
torrent_map::iterator i = m_ses.m_torrents.find(
|
||||
m_torrent_file.info_hash());
|
||||
m_torrent_file->info_hash());
|
||||
assert(i != m_ses.m_torrents.end());
|
||||
m_ses.m_torrents.erase(i);
|
||||
// and notify the thread that it got another
|
||||
|
@ -2291,7 +2291,7 @@ namespace libtorrent
|
|||
if (is_seed())
|
||||
{
|
||||
m_picker.reset();
|
||||
m_torrent_file.seed_free();
|
||||
m_torrent_file->seed_free();
|
||||
}
|
||||
|
||||
if (!m_connections_initialized)
|
||||
|
@ -2374,7 +2374,7 @@ namespace libtorrent
|
|||
|
||||
torrent_handle torrent::get_handle() const
|
||||
{
|
||||
return torrent_handle(&m_ses, &m_checker, m_torrent_file.info_hash());
|
||||
return torrent_handle(&m_ses, &m_checker, m_torrent_file->info_hash());
|
||||
}
|
||||
|
||||
session_settings const& torrent::settings() const
|
||||
|
@ -2417,7 +2417,7 @@ namespace libtorrent
|
|||
|
||||
if (valid_metadata())
|
||||
{
|
||||
assert(m_abort || int(m_have_pieces.size()) == m_torrent_file.num_pieces());
|
||||
assert(m_abort || int(m_have_pieces.size()) == m_torrent_file->num_pieces());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2425,12 +2425,12 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
size_type total_done = quantized_bytes_done();
|
||||
if (m_torrent_file.is_valid())
|
||||
if (m_torrent_file->is_valid())
|
||||
{
|
||||
if (is_seed())
|
||||
assert(total_done == m_torrent_file.total_size());
|
||||
assert(total_done == m_torrent_file->total_size());
|
||||
else
|
||||
assert(total_done != m_torrent_file.total_size());
|
||||
assert(total_done != m_torrent_file->total_size());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2441,7 +2441,7 @@ namespace libtorrent
|
|||
assert(m_num_pieces
|
||||
== std::count(m_have_pieces.begin(), m_have_pieces.end(), true));
|
||||
assert(!valid_metadata() || m_block_size > 0);
|
||||
assert(!valid_metadata() || (m_torrent_file.piece_length() % m_block_size) == 0);
|
||||
assert(!valid_metadata() || (m_torrent_file->piece_length() % m_block_size) == 0);
|
||||
// if (is_seed()) assert(m_picker.get() == 0);
|
||||
}
|
||||
#endif
|
||||
|
@ -2678,7 +2678,7 @@ namespace libtorrent
|
|||
assert(m_storage);
|
||||
assert(m_storage->refcount() > 0);
|
||||
assert(piece_index >= 0);
|
||||
assert(piece_index < m_torrent_file.num_pieces());
|
||||
assert(piece_index < m_torrent_file->num_pieces());
|
||||
assert(piece_index < (int)m_have_pieces.size());
|
||||
|
||||
m_storage->async_hash(piece_index, bind(&torrent::on_piece_verified
|
||||
|
@ -2690,7 +2690,7 @@ namespace libtorrent
|
|||
{
|
||||
sha1_hash h(j.str);
|
||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||
f(m_torrent_file.hash_for_piece(j.piece) == h);
|
||||
f(m_torrent_file->hash_for_piece(j.piece) == h);
|
||||
}
|
||||
|
||||
const tcp::endpoint& torrent::current_tracker() const
|
||||
|
@ -2706,12 +2706,12 @@ namespace libtorrent
|
|||
assert(valid_metadata());
|
||||
|
||||
fp.clear();
|
||||
fp.resize(m_torrent_file.num_files(), 0.f);
|
||||
fp.resize(m_torrent_file->num_files(), 0.f);
|
||||
|
||||
for (int i = 0; i < m_torrent_file.num_files(); ++i)
|
||||
for (int i = 0; i < m_torrent_file->num_files(); ++i)
|
||||
{
|
||||
peer_request ret = m_torrent_file.map_file(i, 0, 0);
|
||||
size_type size = m_torrent_file.file_at(i).size;
|
||||
peer_request ret = m_torrent_file->map_file(i, 0, 0);
|
||||
size_type size = m_torrent_file->file_at(i).size;
|
||||
|
||||
// zero sized files are considered
|
||||
// 100% done all the time
|
||||
|
@ -2724,7 +2724,7 @@ namespace libtorrent
|
|||
size_type done = 0;
|
||||
while (size > 0)
|
||||
{
|
||||
size_type bytes_step = (std::min)(m_torrent_file.piece_size(ret.piece)
|
||||
size_type bytes_step = (std::min)(m_torrent_file->piece_size(ret.piece)
|
||||
- ret.start, size);
|
||||
if (m_have_pieces[ret.piece]) done += bytes_step;
|
||||
++ret.piece;
|
||||
|
@ -2733,7 +2733,7 @@ namespace libtorrent
|
|||
}
|
||||
assert(size == 0);
|
||||
|
||||
fp[i] = static_cast<float>(done) / m_torrent_file.file_at(i).size;
|
||||
fp[i] = static_cast<float>(done) / m_torrent_file->file_at(i).size;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2820,21 +2820,21 @@ namespace libtorrent
|
|||
|
||||
// fill in status that depends on metadata
|
||||
|
||||
st.total_wanted = m_torrent_file.total_size();
|
||||
st.total_wanted = m_torrent_file->total_size();
|
||||
|
||||
if (m_picker.get() && (m_picker->num_filtered() > 0
|
||||
|| m_picker->num_have_filtered() > 0))
|
||||
{
|
||||
int filtered_pieces = m_picker->num_filtered()
|
||||
+ m_picker->num_have_filtered();
|
||||
int last_piece_index = m_torrent_file.num_pieces() - 1;
|
||||
int last_piece_index = m_torrent_file->num_pieces() - 1;
|
||||
if (m_picker->piece_priority(last_piece_index) == 0)
|
||||
{
|
||||
st.total_wanted -= m_torrent_file.piece_size(last_piece_index);
|
||||
st.total_wanted -= m_torrent_file->piece_size(last_piece_index);
|
||||
--filtered_pieces;
|
||||
}
|
||||
|
||||
st.total_wanted -= filtered_pieces * m_torrent_file.piece_length();
|
||||
st.total_wanted -= filtered_pieces * m_torrent_file->piece_length();
|
||||
}
|
||||
|
||||
assert(st.total_wanted >= st.total_wanted_done);
|
||||
|
@ -2852,7 +2852,7 @@ namespace libtorrent
|
|||
}
|
||||
else if (is_seed())
|
||||
{
|
||||
assert(st.total_done == m_torrent_file.total_size());
|
||||
assert(st.total_done == m_torrent_file->total_size());
|
||||
st.state = torrent_status::seeding;
|
||||
}
|
||||
else if (st.total_wanted_done == st.total_wanted)
|
||||
|
|
|
@ -323,7 +323,13 @@ try
|
|||
#endif
|
||||
{
|
||||
using namespace libtorrent::detail;
|
||||
if (e) return;
|
||||
if (e)
|
||||
{
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
m_log << time_now_string() << " *** on_reply aborted: " << e.message() << std::endl;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
// parse out the url for the device
|
||||
|
||||
|
@ -843,9 +849,16 @@ void upnp::on_upnp_map_response(asio::error_code const& e
|
|||
{
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
m_log << time_now_string()
|
||||
<< " <== error while adding portmap: " << p.message() << std::endl;
|
||||
<< " <== error while adding portmap: " << p.status_code() << " " << p.message() << std::endl;
|
||||
#endif
|
||||
m_devices.erase(d);
|
||||
for (int i = 0; i < num_mappings; ++i)
|
||||
{
|
||||
if (d.mapping[i].need_update)
|
||||
{
|
||||
map_port(d, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -69,9 +69,6 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
// we always prefer downloading entire
|
||||
// pieces from web seeds
|
||||
prefer_whole_pieces(true);
|
||||
// we want large blocks as well, so
|
||||
// we can request more bytes at once
|
||||
request_large_blocks(true);
|
||||
|
@ -80,6 +77,10 @@ namespace libtorrent
|
|||
shared_ptr<torrent> tor = t.lock();
|
||||
assert(tor);
|
||||
int blocks_per_piece = tor->torrent_file().piece_length() / tor->block_size();
|
||||
|
||||
// we always prefer downloading 1 MB chunks
|
||||
// from web seeds
|
||||
prefer_whole_pieces((1024 * 1024) / tor->torrent_file().piece_length());
|
||||
|
||||
// multiply with the blocks per piece since that many requests are
|
||||
// merged into one http request
|
||||
|
@ -178,13 +179,16 @@ namespace libtorrent
|
|||
|
||||
int size = r.length;
|
||||
const int block_size = t->block_size();
|
||||
const int piece_size = t->torrent_file().piece_length();
|
||||
peer_request pr;
|
||||
while (size > 0)
|
||||
{
|
||||
int request_size = (std::min)(block_size, size);
|
||||
peer_request pr = {r.piece, r.start + r.length - size
|
||||
, request_size};
|
||||
int request_offset = r.start + r.length - size;
|
||||
pr.start = request_offset % piece_size;
|
||||
pr.length = (std::min)(block_size, size);
|
||||
pr.piece = r.piece + request_offset / piece_size;
|
||||
m_requests.push_back(pr);
|
||||
size -= request_size;
|
||||
size -= pr.length;
|
||||
}
|
||||
|
||||
proxy_settings const& ps = m_ses.web_seed_proxy();
|
||||
|
@ -477,8 +481,11 @@ namespace libtorrent
|
|||
|
||||
peer_request front_request = m_requests.front();
|
||||
|
||||
if (in_range.piece != front_request.piece
|
||||
|| in_range.start > front_request.start + int(m_piece.size()))
|
||||
size_type rs = size_type(in_range.piece) * info.piece_length() + in_range.start;
|
||||
size_type re = rs + in_range.length;
|
||||
size_type fs = size_type(front_request.piece) * info.piece_length() + front_request.start;
|
||||
size_type fe = fs + front_request.length;
|
||||
if (fs < rs || fe > re)
|
||||
{
|
||||
throw std::runtime_error("invalid range in HTTP response");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue