mirror of
https://github.com/codex-storage/deluge.git
synced 2025-02-24 00:58:19 +00:00
lt sync 2667
This commit is contained in:
parent
b210a81967
commit
c78de8f0aa
@ -549,6 +549,10 @@ namespace libtorrent
|
||||
|
||||
udp_socket m_dht_socket;
|
||||
|
||||
// these are used when starting the DHT
|
||||
// (and bootstrapping it), and then erased
|
||||
std::list<std::pair<std::string, int> > m_dht_router_nodes;
|
||||
|
||||
void on_receive_udp(error_code const& e
|
||||
, udp::endpoint const& ep, char const* buf, int len);
|
||||
#endif
|
||||
|
@ -75,6 +75,7 @@ namespace libtorrent
|
||||
, proxy_settings const& ps
|
||||
, std::string const& password = "");
|
||||
|
||||
void start();
|
||||
void close();
|
||||
|
||||
private:
|
||||
@ -92,6 +93,11 @@ namespace libtorrent
|
||||
|
||||
tracker_manager& m_man;
|
||||
boost::shared_ptr<http_connection> m_tracker_connection;
|
||||
session_settings const& m_settings;
|
||||
address m_bind_iface;
|
||||
proxy_settings const& m_ps;
|
||||
connection_queue& m_cc;
|
||||
io_service& m_ios;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -71,8 +71,9 @@ namespace libtorrent { namespace dht
|
||||
{
|
||||
friend void intrusive_ptr_add_ref(dht_tracker const*);
|
||||
friend void intrusive_ptr_release(dht_tracker const*);
|
||||
dht_tracker(udp_socket& sock, dht_settings const& settings
|
||||
, entry const& bootstrap);
|
||||
dht_tracker(udp_socket& sock, dht_settings const& settings);
|
||||
|
||||
void start(entry const& bootstrap);
|
||||
void stop();
|
||||
|
||||
void add_node(udp::endpoint node);
|
||||
|
@ -161,7 +161,7 @@ class node_impl : boost::noncopyable
|
||||
typedef std::map<node_id, torrent_entry> table_t;
|
||||
public:
|
||||
node_impl(boost::function<void(msg const&)> const& f
|
||||
, dht_settings const& settings, boost::optional<node_id> node_id);
|
||||
, dht_settings const& settings);
|
||||
|
||||
virtual ~node_impl() {}
|
||||
|
||||
@ -186,7 +186,9 @@ public:
|
||||
|
||||
typedef table_t::iterator data_iterator;
|
||||
|
||||
void set_node_id(node_id const& nid) { m_id = nid; }
|
||||
node_id const& nid() const { return m_id; }
|
||||
|
||||
boost::tuple<int, int> size() const{ return m_table.size(); }
|
||||
size_type num_global_nodes() const
|
||||
{ return m_table.num_global_nodes(); }
|
||||
|
@ -151,7 +151,7 @@ namespace libtorrent
|
||||
policy::peer* peer_info_struct() const
|
||||
{ return m_peer_info; }
|
||||
|
||||
enum peer_speed_t { slow, medium, fast };
|
||||
enum peer_speed_t { slow = 1, medium, fast };
|
||||
peer_speed_t peer_speed();
|
||||
|
||||
void send_allowed_set();
|
||||
@ -187,6 +187,8 @@ namespace libtorrent
|
||||
bool on_parole() const
|
||||
{ return peer_info_struct() && peer_info_struct()->on_parole; }
|
||||
|
||||
int picker_options() const;
|
||||
|
||||
void prefer_whole_pieces(int num)
|
||||
{ m_prefer_whole_pieces = num; }
|
||||
|
||||
@ -213,7 +215,12 @@ namespace libtorrent
|
||||
|
||||
bool is_seed() const;
|
||||
|
||||
void set_upload_only(bool u) { m_upload_only = u; }
|
||||
void set_upload_only(bool u)
|
||||
{
|
||||
m_upload_only = u;
|
||||
disconnect_if_redundant();
|
||||
}
|
||||
|
||||
bool upload_only() const { return m_upload_only; }
|
||||
|
||||
// will send a keep-alive message to the peer
|
||||
|
@ -88,6 +88,14 @@ namespace libtorrent
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
// the number of priority levels
|
||||
priority_levels = 8,
|
||||
// priority factor
|
||||
prio_factor = priority_levels - 4
|
||||
};
|
||||
|
||||
struct block_info
|
||||
{
|
||||
block_info(): peer(0), num_peers(0), state(state_none) {}
|
||||
@ -110,6 +118,20 @@ namespace libtorrent
|
||||
enum piece_state_t
|
||||
{ none, slow, medium, fast };
|
||||
|
||||
enum options_t
|
||||
{
|
||||
// pick rarest first
|
||||
rarest_first = 1,
|
||||
// pick the most common first, or the last pieces if sequential
|
||||
reverse = 2,
|
||||
// only pick pieces exclusively requested from this peer
|
||||
on_parole = 4,
|
||||
// always pick partial pieces before any other piece
|
||||
prioritize_partials = 8,
|
||||
// pick pieces in sequential order
|
||||
sequential = 16
|
||||
};
|
||||
|
||||
struct downloading_piece
|
||||
{
|
||||
downloading_piece(): finished(0), writing(0), requested(0) {}
|
||||
@ -133,9 +155,6 @@ namespace libtorrent
|
||||
|
||||
void get_availability(std::vector<int>& avail) const;
|
||||
|
||||
void sequential_download(bool sd);
|
||||
bool sequential_download() const { return m_sequential_download >= 0; }
|
||||
|
||||
// increases the peer count for the given piece
|
||||
// (is used when a HAVE message is received)
|
||||
void inc_refcount(int index);
|
||||
@ -161,6 +180,9 @@ namespace libtorrent
|
||||
void we_have(int index);
|
||||
void we_dont_have(int index);
|
||||
|
||||
int cursor() const { return m_cursor; }
|
||||
int reverse_cursor() const { return m_reverse_cursor; }
|
||||
|
||||
// sets all pieces to dont-have
|
||||
void init(int blocks_per_piece, int total_num_blocks);
|
||||
int num_pieces() const { return int(m_piece_map.size()); }
|
||||
@ -202,11 +224,9 @@ namespace libtorrent
|
||||
// The last argument is the policy::peer pointer for the peer that
|
||||
// we'll download from.
|
||||
void pick_pieces(bitfield const& pieces
|
||||
, std::vector<piece_block>& interesting_blocks
|
||||
, int num_pieces, int prefer_whole_pieces
|
||||
, void* peer, piece_state_t speed
|
||||
, bool rarest_first, bool on_parole
|
||||
, std::vector<int> const& suggested_pieces) const;
|
||||
, std::vector<piece_block>& interesting_blocks, int num_blocks
|
||||
, int prefer_whole_pieces, void* peer, piece_state_t speed
|
||||
, int options, std::vector<int> const& suggested_pieces) const;
|
||||
|
||||
// picks blocks from each of the pieces in the piece_list
|
||||
// vector that is also in the piece bitmask. The blocks
|
||||
@ -214,20 +234,23 @@ namespace libtorrent
|
||||
// added to backup_blocks. num blocks is the number of
|
||||
// blocks to be picked. Blocks are not picked from pieces
|
||||
// that are being downloaded
|
||||
int add_blocks(std::vector<int> const& piece_list
|
||||
, bitfield const& pieces
|
||||
, std::vector<piece_block>& interesting_blocks
|
||||
, int num_blocks, int prefer_whole_pieces
|
||||
, void* peer, std::vector<int> const& ignore) const;
|
||||
|
||||
// picks blocks only from downloading pieces
|
||||
int add_blocks_downloading(
|
||||
bitfield const& pieces
|
||||
int add_blocks(int piece, bitfield const& pieces
|
||||
, std::vector<piece_block>& interesting_blocks
|
||||
, std::vector<piece_block>& backup_blocks
|
||||
, std::vector<piece_block>& backup_blocks2
|
||||
, int num_blocks, int prefer_whole_pieces
|
||||
, void* peer, std::vector<int> const& ignore
|
||||
, piece_state_t speed, int options) const;
|
||||
|
||||
// picks blocks only from downloading pieces
|
||||
int add_blocks_downloading(downloading_piece const& dp
|
||||
, bitfield const& pieces
|
||||
, std::vector<piece_block>& interesting_blocks
|
||||
, std::vector<piece_block>& backup_blocks
|
||||
, std::vector<piece_block>& backup_blocks2
|
||||
, int num_blocks, int prefer_whole_pieces
|
||||
, void* peer, piece_state_t speed
|
||||
, bool on_parole) const;
|
||||
, int options) const;
|
||||
|
||||
// clears the peer pointer in all downloading pieces with this
|
||||
// peer pointer
|
||||
@ -291,6 +314,8 @@ namespace libtorrent
|
||||
void check_invariant(const torrent* t = 0) const;
|
||||
void verify_pick(std::vector<piece_block> const& picked
|
||||
, bitfield const& bits) const;
|
||||
#endif
|
||||
#if defined TORRENT_PICKER_LOG || !defined NDEBUG
|
||||
void print_pieces() const;
|
||||
#endif
|
||||
|
||||
@ -313,6 +338,7 @@ namespace libtorrent
|
||||
friend struct piece_pos;
|
||||
|
||||
bool can_pick(int piece, bitfield const& bitmask) const;
|
||||
bool is_piece_free(int piece, bitfield const& bitmask) const;
|
||||
std::pair<int, int> expand_piece(int piece, int whole_pieces
|
||||
, bitfield const& have) const;
|
||||
|
||||
@ -354,7 +380,7 @@ namespace libtorrent
|
||||
// the priority value that means the piece is filtered
|
||||
filter_priority = 0,
|
||||
// the max number the peer count can hold
|
||||
max_peer_count = 0x3ff
|
||||
max_peer_count = 0x3ff,
|
||||
};
|
||||
|
||||
bool have() const { return index == we_have_index; }
|
||||
@ -364,20 +390,41 @@ namespace libtorrent
|
||||
bool filtered() const { return piece_priority == filter_priority; }
|
||||
void filtered(bool f) { piece_priority = f ? filter_priority : 0; }
|
||||
|
||||
// prio 7 is always top priority
|
||||
// prio 0 is always -1 (don't pick)
|
||||
// downloading pieces are always on an even prio_factor priority
|
||||
//
|
||||
// availability x, downloading
|
||||
// | availability x, prio 3; availability 2x, prio 6
|
||||
// | | availability x, prio 2; availability 2x, prio 5
|
||||
// | | | availability x, prio 1; availability 2x, prio 4
|
||||
// | | | |
|
||||
// +---+---+---+---+
|
||||
// | 0 | 1 | 2 | 3 |
|
||||
// +---+---+---+---+
|
||||
|
||||
int priority(piece_picker const* picker) const
|
||||
{
|
||||
if (downloading || filtered()
|
||||
|| have() || peer_count + picker->m_seeds == 0)
|
||||
// filtered pieces (prio = 0), pieces we have or pieces with
|
||||
// availability = 0 should not be present in the piece list
|
||||
// returning -1 indicates that they shouldn't.
|
||||
if (filtered() || have() || peer_count + picker->m_seeds == 0)
|
||||
return -1;
|
||||
|
||||
// priority 5, 6 and 7 disregards availability of the piece
|
||||
if (piece_priority > 4) return 7 - piece_priority;
|
||||
// prio 7 disregards availability
|
||||
if (piece_priority == priority_levels - 1) return 1 - downloading;
|
||||
|
||||
// pieces we are currently downloading have high priority
|
||||
int prio = peer_count * 4;
|
||||
// if (prio >= picker->m_prio_limit * 6) prio = picker->m_prio_limit * 6;
|
||||
// prio 4,5,6 halves the availability of a piece
|
||||
int availability = peer_count;
|
||||
int priority = piece_priority;
|
||||
if (piece_priority >= priority_levels / 2)
|
||||
{
|
||||
availability /= 2;
|
||||
priority -= (priority_levels - 2) / 2;
|
||||
}
|
||||
|
||||
return prio + (4 - piece_priority);
|
||||
if (downloading) return availability * prio_factor;
|
||||
return availability * prio_factor + (priority_levels / 2) - priority;
|
||||
}
|
||||
|
||||
bool operator!=(piece_pos p) const
|
||||
@ -467,11 +514,14 @@ namespace libtorrent
|
||||
// the number of pieces we have
|
||||
int m_num_have;
|
||||
|
||||
// -1 means sequential download is not active.
|
||||
// >= 0 means that pieces are requested in sequential order
|
||||
// and this variable is the next piece to request.
|
||||
// in that case m_pieces is cleared and not used.
|
||||
int m_sequential_download;
|
||||
// we have all pieces in the range [0, m_cursor)
|
||||
// m_cursor is the first piece we don't have
|
||||
int m_cursor;
|
||||
|
||||
// we have all pieces in the range [m_reverse_cursor, end)
|
||||
// m_reverse_cursor is the first piece where we also have
|
||||
// all the subsequent pieces
|
||||
int m_reverse_cursor;
|
||||
|
||||
// if this is set to true, it means update_pieces()
|
||||
// has to be called before accessing m_pieces.
|
||||
|
@ -141,6 +141,7 @@ namespace libtorrent
|
||||
, auto_scrape_min_interval(300)
|
||||
, max_peerlist_size(8000)
|
||||
, min_announce_interval(5 * 60)
|
||||
, prioritize_partial_pieces(false)
|
||||
{}
|
||||
|
||||
// this is the user agent that will be sent to the tracker
|
||||
@ -436,6 +437,10 @@ namespace libtorrent
|
||||
// that is lower than this, will be clamped to this
|
||||
// value. It's specified in seconds
|
||||
int min_announce_interval;
|
||||
|
||||
// if true, partial pieces are picked before pieces
|
||||
// that are more rare
|
||||
bool prioritize_partial_pieces;
|
||||
};
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
|
@ -259,6 +259,8 @@ namespace libtorrent
|
||||
disk_check_aborted = -3
|
||||
};
|
||||
|
||||
storage_interface* get_storage_impl() { return m_storage.get(); }
|
||||
|
||||
private:
|
||||
|
||||
fs::path save_path() const;
|
||||
|
@ -170,6 +170,12 @@ namespace libtorrent
|
||||
int seed_rank(session_settings const& s) const;
|
||||
|
||||
storage_mode_t storage_mode() const { return m_storage_mode; }
|
||||
storage_interface* get_storage()
|
||||
{
|
||||
if (!m_owning_storage) return 0;
|
||||
return m_owning_storage->get_storage_impl();
|
||||
}
|
||||
|
||||
// this will flag the torrent as aborted. The main
|
||||
// loop in session_impl will check for this state
|
||||
// on all torrents once every second, and take
|
||||
|
@ -366,6 +366,8 @@ namespace libtorrent
|
||||
bool resolve_countries() const;
|
||||
#endif
|
||||
|
||||
storage_interface* get_storage_impl() const;
|
||||
|
||||
// all these are deprecated, use piece
|
||||
// priority functions instead
|
||||
|
||||
|
@ -194,6 +194,7 @@ namespace libtorrent
|
||||
|
||||
void fail(int code, char const* msg);
|
||||
void fail_timeout();
|
||||
virtual void start() = 0;
|
||||
virtual void close();
|
||||
address const& bind_interface() const { return m_bind_interface; }
|
||||
|
||||
|
@ -74,6 +74,7 @@ namespace libtorrent
|
||||
, session_settings const& stn
|
||||
, proxy_settings const& ps);
|
||||
|
||||
void start();
|
||||
void close();
|
||||
|
||||
private:
|
||||
|
@ -74,8 +74,9 @@ namespace libtorrent {
|
||||
xt.sec += 1;
|
||||
}
|
||||
xt.nsec = boost::xtime::xtime_nsec_t(nsec);
|
||||
// apparently this call can be interrupted
|
||||
// prematurely if there are other signals
|
||||
if (!m_condition.timed_wait(lock, xt)) return 0;
|
||||
TORRENT_ASSERT(!m_alerts.empty());
|
||||
if (m_alerts.empty()) return 0;
|
||||
return m_alerts.front();
|
||||
}
|
||||
|
@ -945,7 +945,7 @@ namespace libtorrent
|
||||
{
|
||||
std::stringstream msg;
|
||||
msg << "got bitfield with invalid size: " << (packet_size() - 1)
|
||||
<< "bytes. expected: " << ((t->torrent_file().num_pieces() + 7) / 8)
|
||||
<< " bytes. expected: " << ((t->torrent_file().num_pieces() + 7) / 8)
|
||||
<< " bytes";
|
||||
disconnect(msg.str().c_str(), 2);
|
||||
return;
|
||||
@ -1444,7 +1444,7 @@ namespace libtorrent
|
||||
{
|
||||
// don't send a bitfield if we don't have any pieces
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string() << " *** NOT SENDING BITFIELD";
|
||||
(*m_logger) << time_now_string() << " *** NOT SENDING BITFIELD\n";
|
||||
#endif
|
||||
#ifndef NDEBUG
|
||||
m_sent_bitfield = true;
|
||||
|
@ -79,11 +79,19 @@ namespace libtorrent
|
||||
, std::string const& auth)
|
||||
: tracker_connection(man, req, ios, bind_infc, c)
|
||||
, m_man(man)
|
||||
, m_settings(stn)
|
||||
, m_bind_iface(bind_infc)
|
||||
, m_ps(ps)
|
||||
, m_cc(cc)
|
||||
, m_ios(ios)
|
||||
{}
|
||||
|
||||
void http_tracker_connection::start()
|
||||
{
|
||||
// TODO: authentication
|
||||
std::string url = req.url;
|
||||
std::string url = tracker_req().url;
|
||||
|
||||
if (req.kind == tracker_request::scrape_request)
|
||||
if (tracker_req().kind == tracker_request::scrape_request)
|
||||
{
|
||||
// find and replace "announce" with "scrape"
|
||||
// in request
|
||||
@ -91,8 +99,8 @@ namespace libtorrent
|
||||
std::size_t pos = url.find("announce");
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
//fail(-1, ("scrape is not available on url: '"
|
||||
// + req.url +"'").c_str());
|
||||
fail(-1, ("scrape is not available on url: '"
|
||||
+ tracker_req().url +"'").c_str());
|
||||
return;
|
||||
}
|
||||
url.replace(pos, 8, "scrape");
|
||||
@ -109,70 +117,70 @@ namespace libtorrent
|
||||
|
||||
url += "info_hash=";
|
||||
url += escape_string(
|
||||
reinterpret_cast<const char*>(req.info_hash.begin()), 20);
|
||||
reinterpret_cast<const char*>(tracker_req().info_hash.begin()), 20);
|
||||
|
||||
if (req.kind == tracker_request::announce_request)
|
||||
if (tracker_req().kind == tracker_request::announce_request)
|
||||
{
|
||||
url += "&peer_id=";
|
||||
url += escape_string(
|
||||
reinterpret_cast<const char*>(req.pid.begin()), 20);
|
||||
reinterpret_cast<const char*>(tracker_req().pid.begin()), 20);
|
||||
|
||||
url += "&port=";
|
||||
url += boost::lexical_cast<std::string>(req.listen_port);
|
||||
url += boost::lexical_cast<std::string>(tracker_req().listen_port);
|
||||
|
||||
url += "&uploaded=";
|
||||
url += boost::lexical_cast<std::string>(req.uploaded);
|
||||
url += boost::lexical_cast<std::string>(tracker_req().uploaded);
|
||||
|
||||
url += "&downloaded=";
|
||||
url += boost::lexical_cast<std::string>(req.downloaded);
|
||||
url += boost::lexical_cast<std::string>(tracker_req().downloaded);
|
||||
|
||||
url += "&left=";
|
||||
url += boost::lexical_cast<std::string>(req.left);
|
||||
url += boost::lexical_cast<std::string>(tracker_req().left);
|
||||
|
||||
if (req.event != tracker_request::none)
|
||||
if (tracker_req().event != tracker_request::none)
|
||||
{
|
||||
const char* event_string[] = {"completed", "started", "stopped"};
|
||||
url += "&event=";
|
||||
url += event_string[req.event - 1];
|
||||
url += event_string[tracker_req().event - 1];
|
||||
}
|
||||
|
||||
url += "&key=";
|
||||
std::stringstream key_string;
|
||||
key_string << std::hex << req.key;
|
||||
key_string << std::hex << tracker_req().key;
|
||||
url += key_string.str();
|
||||
|
||||
url += "&compact=1";
|
||||
|
||||
url += "&numwant=";
|
||||
url += boost::lexical_cast<std::string>(
|
||||
(std::min)(req.num_want, 999));
|
||||
(std::min)(tracker_req().num_want, 999));
|
||||
|
||||
if (stn.announce_ip != address())
|
||||
if (m_settings.announce_ip != address())
|
||||
{
|
||||
url += "&ip=";
|
||||
url += stn.announce_ip.to_string();
|
||||
url += m_settings.announce_ip.to_string();
|
||||
}
|
||||
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
url += "&supportcrypto=1";
|
||||
#endif
|
||||
url += "&ipv6=";
|
||||
url += req.ipv6;
|
||||
url += tracker_req().ipv6;
|
||||
|
||||
// extension that tells the tracker that
|
||||
// we don't need any peer_id's in the response
|
||||
url += "&no_peer_id=1";
|
||||
}
|
||||
|
||||
m_tracker_connection.reset(new http_connection(ios, cc
|
||||
m_tracker_connection.reset(new http_connection(m_ios, m_cc
|
||||
, boost::bind(&http_tracker_connection::on_response, self(), _1, _2, _3, _4)));
|
||||
|
||||
int timeout = req.event==tracker_request::stopped
|
||||
?stn.stop_tracker_timeout
|
||||
:stn.tracker_completion_timeout;
|
||||
int timeout = tracker_req().event==tracker_request::stopped
|
||||
?m_settings.stop_tracker_timeout
|
||||
:m_settings.tracker_completion_timeout;
|
||||
|
||||
m_tracker_connection->get(url, seconds(timeout)
|
||||
, 1, &ps, 5, stn.user_agent, bind_infc);
|
||||
, 1, &m_ps, 5, m_settings.user_agent, m_bind_iface);
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
|
||||
|
@ -83,21 +83,6 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
boost::optional<node_id> read_id(libtorrent::entry const& d)
|
||||
{
|
||||
using namespace libtorrent;
|
||||
using libtorrent::dht::node_id;
|
||||
|
||||
if (d.type() != entry::dictionary_t) return boost::optional<node_id>();
|
||||
entry const* nid = d.find_key("node-id");
|
||||
if (!nid
|
||||
|| nid->type() != entry::string_t
|
||||
|| nid->string().length() != 40)
|
||||
return boost::optional<node_id>();
|
||||
return boost::optional<node_id>(
|
||||
boost::lexical_cast<node_id>(nid->string()));
|
||||
}
|
||||
|
||||
template <class EndpointType>
|
||||
void read_endpoint_list(libtorrent::entry const* n, std::vector<EndpointType>& epl)
|
||||
{
|
||||
@ -142,10 +127,8 @@ namespace libtorrent { namespace dht
|
||||
|
||||
// class that puts the networking and the kademlia node in a single
|
||||
// unit and connecting them together.
|
||||
dht_tracker::dht_tracker(udp_socket& sock, dht_settings const& settings
|
||||
, entry const& bootstrap)
|
||||
: m_dht(bind(&dht_tracker::send_packet, this, _1), settings
|
||||
, read_id(bootstrap))
|
||||
dht_tracker::dht_tracker(udp_socket& sock, dht_settings const& settings)
|
||||
: m_dht(bind(&dht_tracker::send_packet, this, _1), settings)
|
||||
, m_sock(sock)
|
||||
, m_last_new_key(time_now() - minutes(key_refresh))
|
||||
, m_timer(sock.get_io_service())
|
||||
@ -185,6 +168,10 @@ namespace libtorrent { namespace dht
|
||||
// dht_tracker_log.enable(false);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void dht_tracker::start(entry const& bootstrap)
|
||||
{
|
||||
std::vector<udp::endpoint> initial_nodes;
|
||||
|
||||
if (bootstrap.type() == entry::dictionary_t)
|
||||
@ -194,6 +181,12 @@ namespace libtorrent { namespace dht
|
||||
if (entry const* nodes = bootstrap.find_key("nodes"))
|
||||
read_endpoint_list<udp::endpoint>(nodes, initial_nodes);
|
||||
} catch (std::exception&) {}
|
||||
|
||||
entry const* nid = bootstrap.find_key("node-id");
|
||||
if (nid
|
||||
&& nid->type() == entry::string_t
|
||||
&& nid->string().length() == 40)
|
||||
m_dht.set_node_id(boost::lexical_cast<node_id>(nid->string()));
|
||||
}
|
||||
|
||||
m_timer.expires_from_now(seconds(1));
|
||||
@ -465,6 +458,8 @@ namespace libtorrent { namespace dht
|
||||
m.transaction_id = e["t"].string();
|
||||
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
log_line << " t: " << to_hex(m.transaction_id);
|
||||
|
||||
try
|
||||
{
|
||||
entry const* ver = e.find_key("v");
|
||||
@ -512,8 +507,7 @@ namespace libtorrent { namespace dht
|
||||
if (msg_type == "r")
|
||||
{
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
log_line << " r: " << messages::ids[m.message_id]
|
||||
<< " t: " << to_hex(m.transaction_id);
|
||||
log_line << " r: " << messages::ids[m.message_id];
|
||||
#endif
|
||||
|
||||
m.reply = true;
|
||||
@ -616,7 +610,7 @@ namespace libtorrent { namespace dht
|
||||
if (target.size() != 20) throw std::runtime_error("invalid size of target id");
|
||||
std::copy(target.begin(), target.end(), m.info_hash.begin());
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
log_line << " t: " << boost::lexical_cast<std::string>(m.info_hash);
|
||||
log_line << " target: " << boost::lexical_cast<std::string>(m.info_hash);
|
||||
#endif
|
||||
|
||||
m.message_id = libtorrent::dht::messages::find_node;
|
||||
|
@ -91,9 +91,9 @@ void purge_peers(std::set<peer_entry>& peers)
|
||||
void nop() {}
|
||||
|
||||
node_impl::node_impl(boost::function<void(msg const&)> const& f
|
||||
, dht_settings const& settings, boost::optional<node_id> node_id)
|
||||
, dht_settings const& settings)
|
||||
: m_settings(settings)
|
||||
, m_id(node_id ? *node_id : generate_id())
|
||||
, m_id(generate_id())
|
||||
, m_table(m_id, 8, settings)
|
||||
, m_rpc(bind(&node_impl::incoming_request, this, _1)
|
||||
, m_id, m_table, f)
|
||||
|
@ -572,6 +572,50 @@ namespace libtorrent
|
||||
#endif
|
||||
}
|
||||
|
||||
int peer_connection::picker_options() const
|
||||
{
|
||||
int ret = 0;
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
TORRENT_ASSERT(t);
|
||||
if (!t) return 0;
|
||||
|
||||
if (t->is_sequential_download())
|
||||
{
|
||||
ret |= piece_picker::sequential;
|
||||
}
|
||||
else if (t->num_have() < t->settings().initial_picker_threshold)
|
||||
{
|
||||
// if we have fewer pieces than a certain threshols
|
||||
// don't pick rare pieces, just pick random ones,
|
||||
// and prioritize finishing them
|
||||
ret |= piece_picker::prioritize_partials;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret |= piece_picker::rarest_first;
|
||||
}
|
||||
|
||||
if (m_snubbed)
|
||||
{
|
||||
// snubbed peers should request
|
||||
// the common pieces first, just to make
|
||||
// it more likely for all snubbed peers to
|
||||
// request blocks from the same piece
|
||||
ret |= piece_picker::reverse;
|
||||
}
|
||||
|
||||
if (t->settings().prioritize_partial_pieces)
|
||||
ret |= piece_picker::prioritize_partials;
|
||||
|
||||
if (on_parole()) ret |= piece_picker::on_parole
|
||||
| piece_picker::prioritize_partials;
|
||||
|
||||
// only one of rarest_first, common_first and sequential can be set.
|
||||
TORRENT_ASSERT(bool(ret & piece_picker::rarest_first)
|
||||
+ bool(ret & piece_picker::sequential) <= 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void peer_connection::fast_reconnect(bool r)
|
||||
{
|
||||
if (!peer_info_struct() || peer_info_struct()->fast_reconnects > 1)
|
||||
@ -1129,6 +1173,8 @@ namespace libtorrent
|
||||
<< " <== HAVE [ piece: " << index << "]\n";
|
||||
#endif
|
||||
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
if (!t->valid_metadata() && index > int(m_have_piece.size()))
|
||||
{
|
||||
if (index < 65536)
|
||||
@ -1343,6 +1389,7 @@ namespace libtorrent
|
||||
// if we haven't received a bitfield, it was
|
||||
// probably omitted, which is the same as 'have_none'
|
||||
if (!m_bitfield_received) incoming_have_none();
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
@ -1549,6 +1596,7 @@ namespace libtorrent
|
||||
// if we haven't received a bitfield, it was
|
||||
// probably omitted, which is the same as 'have_none'
|
||||
if (!m_bitfield_received) incoming_have_none();
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
@ -1572,7 +1620,7 @@ namespace libtorrent
|
||||
"s: " << p.start << " | "
|
||||
"l: " << p.length << " | "
|
||||
"ds: " << statistics().download_rate() << " | "
|
||||
"qs: " << m_desired_queue_size << " ]\n";
|
||||
"qs: " << int(m_desired_queue_size) << " ]\n";
|
||||
#endif
|
||||
|
||||
if (p.length == 0)
|
||||
@ -1639,7 +1687,7 @@ namespace libtorrent
|
||||
return;
|
||||
}
|
||||
|
||||
int block_index = b - m_download_queue.begin();
|
||||
int block_index = b - m_download_queue.begin() - 1;
|
||||
for (int i = 0; i < block_index; ++i)
|
||||
{
|
||||
pending_block& qe = m_download_queue[i];
|
||||
@ -1660,6 +1708,7 @@ namespace libtorrent
|
||||
m_ses.m_alerts.post_alert(request_dropped_alert(t->get_handle()
|
||||
, remote(), pid(), qe.block.block_index, qe.block.piece_index));
|
||||
picker.abort_download(qe.block);
|
||||
TORRENT_ASSERT(m_download_queue.begin() + i != b);
|
||||
m_download_queue.erase(m_download_queue.begin() + i);
|
||||
--i;
|
||||
--block_index;
|
||||
@ -1723,9 +1772,12 @@ namespace libtorrent
|
||||
bool multi = picker.num_peers(block_finished) > 1;
|
||||
picker.mark_as_writing(block_finished, peer_info_struct());
|
||||
|
||||
TORRENT_ASSERT(picker.num_peers(block_finished) == 0);
|
||||
// if we requested this block from other peers, cancel it now
|
||||
if (multi) t->cancel_block(block_finished);
|
||||
|
||||
TORRENT_ASSERT(picker.num_peers(block_finished) == 0);
|
||||
|
||||
#if !defined NDEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS
|
||||
t->check_invariant();
|
||||
#endif
|
||||
@ -1776,6 +1828,7 @@ namespace libtorrent
|
||||
|
||||
TORRENT_ASSERT(p.piece == j.piece);
|
||||
TORRENT_ASSERT(p.start == j.offset);
|
||||
TORRENT_ASSERT(picker.num_peers(block_finished) == 0);
|
||||
picker.mark_as_finished(block_finished, peer_info_struct());
|
||||
if (t->alerts().should_post<block_finished_alert>())
|
||||
{
|
||||
@ -2332,7 +2385,7 @@ namespace libtorrent
|
||||
"s: " << r.start << " | "
|
||||
"l: " << r.length << " | "
|
||||
"ds: " << statistics().download_rate() << " B/s | "
|
||||
"qs: " << m_desired_queue_size << " "
|
||||
"qs: " << int(m_desired_queue_size) << " "
|
||||
"blk: " << (m_request_large_blocks?"large":"single") << " ]\n";
|
||||
#endif
|
||||
}
|
||||
@ -3898,7 +3951,7 @@ namespace libtorrent
|
||||
m_speed = medium;
|
||||
else if (download_rate < torrent_download_rate / 15 && m_speed == fast)
|
||||
m_speed = medium;
|
||||
else if (download_rate < torrent_download_rate / 63 && m_speed == medium)
|
||||
else
|
||||
m_speed = slow;
|
||||
|
||||
return m_speed;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -200,8 +200,6 @@ namespace libtorrent
|
||||
|
||||
int prefer_whole_pieces = c.prefer_whole_pieces();
|
||||
|
||||
bool rarest_first = t.num_have() >= t.settings().initial_picker_threshold;
|
||||
|
||||
if (prefer_whole_pieces == 0)
|
||||
{
|
||||
prefer_whole_pieces = c.statistics().download_payload_rate()
|
||||
@ -250,7 +248,7 @@ namespace libtorrent
|
||||
|
||||
p.pick_pieces(mask, interesting_pieces
|
||||
, num_requests, prefer_whole_pieces, c.peer_info_struct()
|
||||
, state, rarest_first, c.on_parole(), suggested);
|
||||
, state, c.picker_options(), suggested);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -264,7 +262,7 @@ namespace libtorrent
|
||||
// then use this mode.
|
||||
p.pick_pieces(bits, interesting_pieces
|
||||
, num_requests, prefer_whole_pieces, c.peer_info_struct()
|
||||
, state, rarest_first, c.on_parole(), suggested);
|
||||
, state, c.picker_options(), suggested);
|
||||
}
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
@ -303,10 +301,6 @@ namespace libtorrent
|
||||
|
||||
if (busy_pieces.empty() || num_requests <= 0)
|
||||
{
|
||||
// in this case, we could not find any blocks
|
||||
// that was free. If we couldn't find any busy
|
||||
// blocks as well, we cannot download anything
|
||||
// more from this peer.
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1494,67 +1494,71 @@ namespace aux {
|
||||
}
|
||||
}
|
||||
|
||||
m_optimistic_unchoke_time_scaler--;
|
||||
if (m_optimistic_unchoke_time_scaler <= 0)
|
||||
if (m_allowed_upload_slots > 0)
|
||||
{
|
||||
m_optimistic_unchoke_time_scaler
|
||||
= settings().optimistic_unchoke_multiplier;
|
||||
|
||||
// find the peer that has been waiting the longest to be optimistically
|
||||
// unchoked
|
||||
connection_map::iterator current_optimistic_unchoke = m_connections.end();
|
||||
connection_map::iterator optimistic_unchoke_candidate = m_connections.end();
|
||||
ptime last_unchoke = max_time();
|
||||
|
||||
for (connection_map::iterator i = m_connections.begin()
|
||||
, end(m_connections.end()); i != end; ++i)
|
||||
m_optimistic_unchoke_time_scaler--;
|
||||
if (m_optimistic_unchoke_time_scaler <= 0)
|
||||
{
|
||||
peer_connection* p = i->get();
|
||||
TORRENT_ASSERT(p);
|
||||
policy::peer* pi = p->peer_info_struct();
|
||||
if (!pi) continue;
|
||||
torrent* t = p->associated_torrent().lock().get();
|
||||
if (!t) continue;
|
||||
m_optimistic_unchoke_time_scaler
|
||||
= settings().optimistic_unchoke_multiplier;
|
||||
|
||||
if (pi->optimistically_unchoked)
|
||||
// find the peer that has been waiting the longest to be optimistically
|
||||
// unchoked
|
||||
connection_map::iterator current_optimistic_unchoke = m_connections.end();
|
||||
connection_map::iterator optimistic_unchoke_candidate = m_connections.end();
|
||||
ptime last_unchoke = max_time();
|
||||
|
||||
for (connection_map::iterator i = m_connections.begin()
|
||||
, end(m_connections.end()); i != end; ++i)
|
||||
{
|
||||
TORRENT_ASSERT(!p->is_choked());
|
||||
TORRENT_ASSERT(current_optimistic_unchoke == m_connections.end());
|
||||
current_optimistic_unchoke = i;
|
||||
peer_connection* p = i->get();
|
||||
TORRENT_ASSERT(p);
|
||||
policy::peer* pi = p->peer_info_struct();
|
||||
if (!pi) continue;
|
||||
torrent* t = p->associated_torrent().lock().get();
|
||||
if (!t) continue;
|
||||
|
||||
if (pi->optimistically_unchoked)
|
||||
{
|
||||
TORRENT_ASSERT(!p->is_choked());
|
||||
TORRENT_ASSERT(current_optimistic_unchoke == m_connections.end());
|
||||
current_optimistic_unchoke = i;
|
||||
}
|
||||
|
||||
if (pi->last_optimistically_unchoked < last_unchoke
|
||||
&& !p->is_connecting()
|
||||
&& !p->is_disconnecting()
|
||||
&& p->is_peer_interested()
|
||||
&& t->free_upload_slots()
|
||||
&& p->is_choked()
|
||||
&& t->valid_metadata())
|
||||
{
|
||||
last_unchoke = pi->last_optimistically_unchoked;
|
||||
optimistic_unchoke_candidate = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (pi->last_optimistically_unchoked < last_unchoke
|
||||
&& !p->is_connecting()
|
||||
&& !p->is_disconnecting()
|
||||
&& p->is_peer_interested()
|
||||
&& t->free_upload_slots()
|
||||
&& p->is_choked())
|
||||
if (optimistic_unchoke_candidate != m_connections.end()
|
||||
&& optimistic_unchoke_candidate != current_optimistic_unchoke)
|
||||
{
|
||||
last_unchoke = pi->last_optimistically_unchoked;
|
||||
optimistic_unchoke_candidate = i;
|
||||
}
|
||||
}
|
||||
if (current_optimistic_unchoke != m_connections.end())
|
||||
{
|
||||
torrent* t = (*current_optimistic_unchoke)->associated_torrent().lock().get();
|
||||
TORRENT_ASSERT(t);
|
||||
(*current_optimistic_unchoke)->peer_info_struct()->optimistically_unchoked = false;
|
||||
t->choke_peer(*current_optimistic_unchoke->get());
|
||||
}
|
||||
else
|
||||
{
|
||||
++m_num_unchoked;
|
||||
}
|
||||
|
||||
if (optimistic_unchoke_candidate != m_connections.end()
|
||||
&& optimistic_unchoke_candidate != current_optimistic_unchoke)
|
||||
{
|
||||
if (current_optimistic_unchoke != m_connections.end())
|
||||
{
|
||||
torrent* t = (*current_optimistic_unchoke)->associated_torrent().lock().get();
|
||||
torrent* t = (*optimistic_unchoke_candidate)->associated_torrent().lock().get();
|
||||
TORRENT_ASSERT(t);
|
||||
(*current_optimistic_unchoke)->peer_info_struct()->optimistically_unchoked = false;
|
||||
t->choke_peer(*current_optimistic_unchoke->get());
|
||||
bool ret = t->unchoke_peer(*optimistic_unchoke_candidate->get());
|
||||
TORRENT_ASSERT(ret);
|
||||
(*optimistic_unchoke_candidate)->peer_info_struct()->optimistically_unchoked = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
++m_num_unchoked;
|
||||
}
|
||||
|
||||
torrent* t = (*optimistic_unchoke_candidate)->associated_torrent().lock().get();
|
||||
TORRENT_ASSERT(t);
|
||||
bool ret = t->unchoke_peer(*optimistic_unchoke_candidate->get());
|
||||
TORRENT_ASSERT(ret);
|
||||
(*optimistic_unchoke_candidate)->peer_info_struct()->optimistically_unchoked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2046,11 +2050,20 @@ namespace aux {
|
||||
, m_dht_settings.service_port
|
||||
, m_dht_settings.service_port);
|
||||
}
|
||||
m_dht = new dht::dht_tracker(m_dht_socket, m_dht_settings, startup_state);
|
||||
m_dht = new dht::dht_tracker(m_dht_socket, m_dht_settings);
|
||||
if (!m_dht_socket.is_open() || m_dht_socket.local_port() != m_dht_settings.service_port)
|
||||
{
|
||||
m_dht_socket.bind(m_dht_settings.service_port);
|
||||
}
|
||||
|
||||
for (std::list<std::pair<std::string, int> >::iterator i = m_dht_router_nodes.begin()
|
||||
, end(m_dht_router_nodes.end()); i != end; ++i)
|
||||
{
|
||||
m_dht->add_router_node(*i);
|
||||
}
|
||||
std::list<std::pair<std::string, int> >().swap(m_dht_router_nodes);
|
||||
|
||||
m_dht->start(startup_state);
|
||||
}
|
||||
|
||||
void session_impl::stop_dht()
|
||||
@ -2114,9 +2127,10 @@ namespace aux {
|
||||
|
||||
void session_impl::add_dht_router(std::pair<std::string, int> const& node)
|
||||
{
|
||||
TORRENT_ASSERT(m_dht);
|
||||
// router nodes should be added before the DHT is started (and bootstrapped)
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
m_dht->add_router_node(node);
|
||||
if (m_dht) m_dht->add_router_node(node);
|
||||
else m_dht_router_nodes.push_back(node);
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -2167,7 +2181,7 @@ namespace aux {
|
||||
|
||||
void session_impl::set_max_uploads(int limit)
|
||||
{
|
||||
TORRENT_ASSERT(limit > 0 || limit == -1);
|
||||
TORRENT_ASSERT(limit >= 0 || limit == -1);
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
|
||||
INVARIANT_CHECK;
|
||||
|
@ -754,10 +754,14 @@ namespace libtorrent
|
||||
|
||||
m_progress = j.piece / float(torrent_file().num_pieces());
|
||||
|
||||
m_picker->check_invariant();
|
||||
|
||||
TORRENT_ASSERT(m_picker);
|
||||
if (j.offset >= 0 && !m_picker->have_piece(j.offset))
|
||||
m_picker->we_have(j.offset);
|
||||
|
||||
m_picker->check_invariant();
|
||||
|
||||
// we're not done checking yet
|
||||
// this handler will be called repeatedly until
|
||||
// we're done, or encounter a failure
|
||||
@ -3298,9 +3302,6 @@ namespace libtorrent
|
||||
|
||||
if (!is_seed())
|
||||
{
|
||||
if (m_sequential_download)
|
||||
picker().sequential_download(m_sequential_download);
|
||||
|
||||
// if we just finished checking and we're not a seed, we are
|
||||
// likely to be unpaused
|
||||
if (m_ses.m_auto_manage_time_scaler > 1)
|
||||
@ -3549,13 +3550,7 @@ namespace libtorrent
|
||||
#endif
|
||||
|
||||
void torrent::set_sequential_download(bool sd)
|
||||
{
|
||||
m_sequential_download = sd;
|
||||
if (has_picker())
|
||||
{
|
||||
picker().sequential_download(sd);
|
||||
}
|
||||
}
|
||||
{ m_sequential_download = sd; }
|
||||
|
||||
void torrent::set_queue_position(int p)
|
||||
{
|
||||
|
@ -499,6 +499,12 @@ namespace libtorrent
|
||||
TORRENT_FORWARD(replace_trackers(urls));
|
||||
}
|
||||
|
||||
storage_interface* torrent_handle::get_storage_impl() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
TORRENT_FORWARD_RETURN(get_storage(), 0);
|
||||
}
|
||||
|
||||
torrent_info const& torrent_handle::get_torrent_info() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
@ -229,6 +229,7 @@ namespace libtorrent
|
||||
|
||||
boost::shared_ptr<request_callback> cb = con->requester();
|
||||
if (cb) cb->m_manager = this;
|
||||
con->start();
|
||||
}
|
||||
|
||||
void tracker_manager::abort_all_requests()
|
||||
|
@ -93,14 +93,17 @@ namespace libtorrent
|
||||
, m_state(action_error)
|
||||
{
|
||||
m_socket.set_proxy_settings(proxy);
|
||||
}
|
||||
|
||||
void udp_tracker_connection::start()
|
||||
{
|
||||
std::string hostname;
|
||||
int port;
|
||||
char const* error;
|
||||
|
||||
using boost::tuples::ignore;
|
||||
boost::tie(ignore, ignore, hostname, port, ignore, error)
|
||||
= parse_url_components(req.url);
|
||||
= parse_url_components(tracker_req().url);
|
||||
|
||||
if (error)
|
||||
{
|
||||
@ -112,7 +115,7 @@ namespace libtorrent
|
||||
m_name_lookup.async_resolve(q
|
||||
, boost::bind(
|
||||
&udp_tracker_connection::name_lookup, self(), _1, _2));
|
||||
set_timeout(req.event == tracker_request::stopped
|
||||
set_timeout(tracker_req().event == tracker_request::stopped
|
||||
? m_settings.stop_tracker_timeout
|
||||
: m_settings.tracker_completion_timeout
|
||||
, m_settings.tracker_receive_timeout);
|
||||
|
Loading…
x
Reference in New Issue
Block a user