lt sync 2667

This commit is contained in:
Andrew Resch 2008-09-07 10:44:46 +00:00
commit bd8dcbce91
25 changed files with 925 additions and 529 deletions

View file

@ -549,6 +549,10 @@ namespace libtorrent
udp_socket m_dht_socket; 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 void on_receive_udp(error_code const& e
, udp::endpoint const& ep, char const* buf, int len); , udp::endpoint const& ep, char const* buf, int len);
#endif #endif

View file

@ -75,6 +75,7 @@ namespace libtorrent
, proxy_settings const& ps , proxy_settings const& ps
, std::string const& password = ""); , std::string const& password = "");
void start();
void close(); void close();
private: private:
@ -92,6 +93,11 @@ namespace libtorrent
tracker_manager& m_man; tracker_manager& m_man;
boost::shared_ptr<http_connection> m_tracker_connection; 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;
}; };
} }

View file

@ -71,8 +71,9 @@ namespace libtorrent { namespace dht
{ {
friend void intrusive_ptr_add_ref(dht_tracker const*); friend void intrusive_ptr_add_ref(dht_tracker const*);
friend void intrusive_ptr_release(dht_tracker const*); friend void intrusive_ptr_release(dht_tracker const*);
dht_tracker(udp_socket& sock, dht_settings const& settings dht_tracker(udp_socket& sock, dht_settings const& settings);
, entry const& bootstrap);
void start(entry const& bootstrap);
void stop(); void stop();
void add_node(udp::endpoint node); void add_node(udp::endpoint node);

View file

@ -161,7 +161,7 @@ class node_impl : boost::noncopyable
typedef std::map<node_id, torrent_entry> table_t; typedef std::map<node_id, torrent_entry> table_t;
public: public:
node_impl(boost::function<void(msg const&)> const& f 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() {} virtual ~node_impl() {}
@ -186,7 +186,9 @@ public:
typedef table_t::iterator data_iterator; 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; } node_id const& nid() const { return m_id; }
boost::tuple<int, int> size() const{ return m_table.size(); } boost::tuple<int, int> size() const{ return m_table.size(); }
size_type num_global_nodes() const size_type num_global_nodes() const
{ return m_table.num_global_nodes(); } { return m_table.num_global_nodes(); }

View file

@ -151,7 +151,7 @@ namespace libtorrent
policy::peer* peer_info_struct() const policy::peer* peer_info_struct() const
{ return m_peer_info; } { return m_peer_info; }
enum peer_speed_t { slow, medium, fast }; enum peer_speed_t { slow = 1, medium, fast };
peer_speed_t peer_speed(); peer_speed_t peer_speed();
void send_allowed_set(); void send_allowed_set();
@ -187,6 +187,8 @@ namespace libtorrent
bool on_parole() const bool on_parole() const
{ return peer_info_struct() && peer_info_struct()->on_parole; } { return peer_info_struct() && peer_info_struct()->on_parole; }
int picker_options() const;
void prefer_whole_pieces(int num) void prefer_whole_pieces(int num)
{ m_prefer_whole_pieces = num; } { m_prefer_whole_pieces = num; }
@ -213,7 +215,12 @@ namespace libtorrent
bool is_seed() const; 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; } bool upload_only() const { return m_upload_only; }
// will send a keep-alive message to the peer // will send a keep-alive message to the peer

View file

@ -88,6 +88,14 @@ namespace libtorrent
{ {
public: public:
enum
{
// the number of priority levels
priority_levels = 8,
// priority factor
prio_factor = priority_levels - 4
};
struct block_info struct block_info
{ {
block_info(): peer(0), num_peers(0), state(state_none) {} block_info(): peer(0), num_peers(0), state(state_none) {}
@ -110,6 +118,20 @@ namespace libtorrent
enum piece_state_t enum piece_state_t
{ none, slow, medium, fast }; { 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 struct downloading_piece
{ {
downloading_piece(): finished(0), writing(0), requested(0) {} downloading_piece(): finished(0), writing(0), requested(0) {}
@ -133,9 +155,6 @@ namespace libtorrent
void get_availability(std::vector<int>& avail) const; 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 // increases the peer count for the given piece
// (is used when a HAVE message is received) // (is used when a HAVE message is received)
void inc_refcount(int index); void inc_refcount(int index);
@ -161,6 +180,9 @@ namespace libtorrent
void we_have(int index); void we_have(int index);
void we_dont_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 // sets all pieces to dont-have
void init(int blocks_per_piece, int total_num_blocks); void init(int blocks_per_piece, int total_num_blocks);
int num_pieces() const { return int(m_piece_map.size()); } 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 // The last argument is the policy::peer pointer for the peer that
// we'll download from. // we'll download from.
void pick_pieces(bitfield const& pieces void pick_pieces(bitfield const& pieces
, std::vector<piece_block>& interesting_blocks , std::vector<piece_block>& interesting_blocks, int num_blocks
, int num_pieces, int prefer_whole_pieces , int prefer_whole_pieces, void* peer, piece_state_t speed
, void* peer, piece_state_t speed , int options, std::vector<int> const& suggested_pieces) const;
, bool rarest_first, bool on_parole
, std::vector<int> const& suggested_pieces) const;
// picks blocks from each of the pieces in the piece_list // picks blocks from each of the pieces in the piece_list
// vector that is also in the piece bitmask. The blocks // 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 // added to backup_blocks. num blocks is the number of
// blocks to be picked. Blocks are not picked from pieces // blocks to be picked. Blocks are not picked from pieces
// that are being downloaded // that are being downloaded
int add_blocks(std::vector<int> const& piece_list int add_blocks(int piece, bitfield const& pieces
, 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
, std::vector<piece_block>& interesting_blocks , std::vector<piece_block>& interesting_blocks
, std::vector<piece_block>& backup_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 , int num_blocks, int prefer_whole_pieces
, void* peer, piece_state_t speed , void* peer, piece_state_t speed
, bool on_parole) const; , int options) const;
// clears the peer pointer in all downloading pieces with this // clears the peer pointer in all downloading pieces with this
// peer pointer // peer pointer
@ -291,6 +314,8 @@ namespace libtorrent
void check_invariant(const torrent* t = 0) const; void check_invariant(const torrent* t = 0) const;
void verify_pick(std::vector<piece_block> const& picked void verify_pick(std::vector<piece_block> const& picked
, bitfield const& bits) const; , bitfield const& bits) const;
#endif
#if defined TORRENT_PICKER_LOG || !defined NDEBUG
void print_pieces() const; void print_pieces() const;
#endif #endif
@ -313,6 +338,7 @@ namespace libtorrent
friend struct piece_pos; friend struct piece_pos;
bool can_pick(int piece, bitfield const& bitmask) const; 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 std::pair<int, int> expand_piece(int piece, int whole_pieces
, bitfield const& have) const; , bitfield const& have) const;
@ -354,7 +380,7 @@ namespace libtorrent
// the priority value that means the piece is filtered // the priority value that means the piece is filtered
filter_priority = 0, filter_priority = 0,
// the max number the peer count can hold // the max number the peer count can hold
max_peer_count = 0x3ff max_peer_count = 0x3ff,
}; };
bool have() const { return index == we_have_index; } bool have() const { return index == we_have_index; }
@ -364,20 +390,41 @@ namespace libtorrent
bool filtered() const { return piece_priority == filter_priority; } bool filtered() const { return piece_priority == filter_priority; }
void filtered(bool f) { piece_priority = f ? filter_priority : 0; } 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 int priority(piece_picker const* picker) const
{ {
if (downloading || filtered() // filtered pieces (prio = 0), pieces we have or pieces with
|| have() || peer_count + picker->m_seeds == 0) // 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; return -1;
// priority 5, 6 and 7 disregards availability of the piece // prio 7 disregards availability
if (piece_priority > 4) return 7 - piece_priority; if (piece_priority == priority_levels - 1) return 1 - downloading;
// pieces we are currently downloading have high priority // prio 4,5,6 halves the availability of a piece
int prio = peer_count * 4; int availability = peer_count;
// if (prio >= picker->m_prio_limit * 6) prio = picker->m_prio_limit * 6; 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 bool operator!=(piece_pos p) const
@ -467,11 +514,14 @@ namespace libtorrent
// the number of pieces we have // the number of pieces we have
int m_num_have; int m_num_have;
// -1 means sequential download is not active. // we have all pieces in the range [0, m_cursor)
// >= 0 means that pieces are requested in sequential order // m_cursor is the first piece we don't have
// and this variable is the next piece to request. int m_cursor;
// in that case m_pieces is cleared and not used.
int m_sequential_download; // 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() // if this is set to true, it means update_pieces()
// has to be called before accessing m_pieces. // has to be called before accessing m_pieces.

View file

@ -141,6 +141,7 @@ namespace libtorrent
, auto_scrape_min_interval(300) , auto_scrape_min_interval(300)
, max_peerlist_size(8000) , max_peerlist_size(8000)
, min_announce_interval(5 * 60) , min_announce_interval(5 * 60)
, prioritize_partial_pieces(false)
{} {}
// this is the user agent that will be sent to the tracker // 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 // that is lower than this, will be clamped to this
// value. It's specified in seconds // value. It's specified in seconds
int min_announce_interval; int min_announce_interval;
// if true, partial pieces are picked before pieces
// that are more rare
bool prioritize_partial_pieces;
}; };
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT

View file

@ -259,6 +259,8 @@ namespace libtorrent
disk_check_aborted = -3 disk_check_aborted = -3
}; };
storage_interface* get_storage_impl() { return m_storage.get(); }
private: private:
fs::path save_path() const; fs::path save_path() const;

View file

@ -170,6 +170,12 @@ namespace libtorrent
int seed_rank(session_settings const& s) const; int seed_rank(session_settings const& s) const;
storage_mode_t storage_mode() const { return m_storage_mode; } 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 // this will flag the torrent as aborted. The main
// loop in session_impl will check for this state // loop in session_impl will check for this state
// on all torrents once every second, and take // on all torrents once every second, and take

View file

@ -366,6 +366,8 @@ namespace libtorrent
bool resolve_countries() const; bool resolve_countries() const;
#endif #endif
storage_interface* get_storage_impl() const;
// all these are deprecated, use piece // all these are deprecated, use piece
// priority functions instead // priority functions instead

View file

@ -194,6 +194,7 @@ namespace libtorrent
void fail(int code, char const* msg); void fail(int code, char const* msg);
void fail_timeout(); void fail_timeout();
virtual void start() = 0;
virtual void close(); virtual void close();
address const& bind_interface() const { return m_bind_interface; } address const& bind_interface() const { return m_bind_interface; }

View file

@ -74,6 +74,7 @@ namespace libtorrent
, session_settings const& stn , session_settings const& stn
, proxy_settings const& ps); , proxy_settings const& ps);
void start();
void close(); void close();
private: private:

View file

@ -74,8 +74,9 @@ namespace libtorrent {
xt.sec += 1; xt.sec += 1;
} }
xt.nsec = boost::xtime::xtime_nsec_t(nsec); 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; if (!m_condition.timed_wait(lock, xt)) return 0;
TORRENT_ASSERT(!m_alerts.empty());
if (m_alerts.empty()) return 0; if (m_alerts.empty()) return 0;
return m_alerts.front(); return m_alerts.front();
} }

View file

@ -945,7 +945,7 @@ namespace libtorrent
{ {
std::stringstream msg; std::stringstream msg;
msg << "got bitfield with invalid size: " << (packet_size() - 1) 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"; << " bytes";
disconnect(msg.str().c_str(), 2); disconnect(msg.str().c_str(), 2);
return; return;
@ -1444,7 +1444,7 @@ namespace libtorrent
{ {
// don't send a bitfield if we don't have any pieces // don't send a bitfield if we don't have any pieces
#ifdef TORRENT_VERBOSE_LOGGING #ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string() << " *** NOT SENDING BITFIELD"; (*m_logger) << time_now_string() << " *** NOT SENDING BITFIELD\n";
#endif #endif
#ifndef NDEBUG #ifndef NDEBUG
m_sent_bitfield = true; m_sent_bitfield = true;

View file

@ -79,11 +79,19 @@ namespace libtorrent
, std::string const& auth) , std::string const& auth)
: tracker_connection(man, req, ios, bind_infc, c) : tracker_connection(man, req, ios, bind_infc, c)
, m_man(man) , 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 // 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" // find and replace "announce" with "scrape"
// in request // in request
@ -91,8 +99,8 @@ namespace libtorrent
std::size_t pos = url.find("announce"); std::size_t pos = url.find("announce");
if (pos == std::string::npos) if (pos == std::string::npos)
{ {
//fail(-1, ("scrape is not available on url: '" fail(-1, ("scrape is not available on url: '"
// + req.url +"'").c_str()); + tracker_req().url +"'").c_str());
return; return;
} }
url.replace(pos, 8, "scrape"); url.replace(pos, 8, "scrape");
@ -109,70 +117,70 @@ namespace libtorrent
url += "info_hash="; url += "info_hash=";
url += escape_string( 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 += "&peer_id=";
url += escape_string( url += escape_string(
reinterpret_cast<const char*>(req.pid.begin()), 20); reinterpret_cast<const char*>(tracker_req().pid.begin()), 20);
url += "&port="; url += "&port=";
url += boost::lexical_cast<std::string>(req.listen_port); url += boost::lexical_cast<std::string>(tracker_req().listen_port);
url += "&uploaded="; url += "&uploaded=";
url += boost::lexical_cast<std::string>(req.uploaded); url += boost::lexical_cast<std::string>(tracker_req().uploaded);
url += "&downloaded="; url += "&downloaded=";
url += boost::lexical_cast<std::string>(req.downloaded); url += boost::lexical_cast<std::string>(tracker_req().downloaded);
url += "&left="; 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"}; const char* event_string[] = {"completed", "started", "stopped"};
url += "&event="; url += "&event=";
url += event_string[req.event - 1]; url += event_string[tracker_req().event - 1];
} }
url += "&key="; url += "&key=";
std::stringstream key_string; std::stringstream key_string;
key_string << std::hex << req.key; key_string << std::hex << tracker_req().key;
url += key_string.str(); url += key_string.str();
url += "&compact=1"; url += "&compact=1";
url += "&numwant="; url += "&numwant=";
url += boost::lexical_cast<std::string>( 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 += "&ip=";
url += stn.announce_ip.to_string(); url += m_settings.announce_ip.to_string();
} }
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
url += "&supportcrypto=1"; url += "&supportcrypto=1";
#endif #endif
url += "&ipv6="; url += "&ipv6=";
url += req.ipv6; url += tracker_req().ipv6;
// extension that tells the tracker that // extension that tells the tracker that
// we don't need any peer_id's in the response // we don't need any peer_id's in the response
url += "&no_peer_id=1"; 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))); , boost::bind(&http_tracker_connection::on_response, self(), _1, _2, _3, _4)));
int timeout = req.event==tracker_request::stopped int timeout = tracker_req().event==tracker_request::stopped
?stn.stop_tracker_timeout ?m_settings.stop_tracker_timeout
:stn.tracker_completion_timeout; :m_settings.tracker_completion_timeout;
m_tracker_connection->get(url, seconds(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) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)

View file

@ -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> template <class EndpointType>
void read_endpoint_list(libtorrent::entry const* n, std::vector<EndpointType>& epl) 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 // class that puts the networking and the kademlia node in a single
// unit and connecting them together. // unit and connecting them together.
dht_tracker::dht_tracker(udp_socket& sock, dht_settings const& settings dht_tracker::dht_tracker(udp_socket& sock, dht_settings const& settings)
, entry const& bootstrap) : m_dht(bind(&dht_tracker::send_packet, this, _1), settings)
: m_dht(bind(&dht_tracker::send_packet, this, _1), settings
, read_id(bootstrap))
, m_sock(sock) , m_sock(sock)
, m_last_new_key(time_now() - minutes(key_refresh)) , m_last_new_key(time_now() - minutes(key_refresh))
, m_timer(sock.get_io_service()) , m_timer(sock.get_io_service())
@ -185,6 +168,10 @@ namespace libtorrent { namespace dht
// dht_tracker_log.enable(false); // dht_tracker_log.enable(false);
#endif #endif
}
void dht_tracker::start(entry const& bootstrap)
{
std::vector<udp::endpoint> initial_nodes; std::vector<udp::endpoint> initial_nodes;
if (bootstrap.type() == entry::dictionary_t) if (bootstrap.type() == entry::dictionary_t)
@ -194,6 +181,12 @@ namespace libtorrent { namespace dht
if (entry const* nodes = bootstrap.find_key("nodes")) if (entry const* nodes = bootstrap.find_key("nodes"))
read_endpoint_list<udp::endpoint>(nodes, initial_nodes); read_endpoint_list<udp::endpoint>(nodes, initial_nodes);
} catch (std::exception&) {} } 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)); m_timer.expires_from_now(seconds(1));
@ -465,6 +458,8 @@ namespace libtorrent { namespace dht
m.transaction_id = e["t"].string(); m.transaction_id = e["t"].string();
#ifdef TORRENT_DHT_VERBOSE_LOGGING #ifdef TORRENT_DHT_VERBOSE_LOGGING
log_line << " t: " << to_hex(m.transaction_id);
try try
{ {
entry const* ver = e.find_key("v"); entry const* ver = e.find_key("v");
@ -512,8 +507,7 @@ namespace libtorrent { namespace dht
if (msg_type == "r") if (msg_type == "r")
{ {
#ifdef TORRENT_DHT_VERBOSE_LOGGING #ifdef TORRENT_DHT_VERBOSE_LOGGING
log_line << " r: " << messages::ids[m.message_id] log_line << " r: " << messages::ids[m.message_id];
<< " t: " << to_hex(m.transaction_id);
#endif #endif
m.reply = true; m.reply = true;
@ -616,7 +610,7 @@ namespace libtorrent { namespace dht
if (target.size() != 20) throw std::runtime_error("invalid size of target id"); if (target.size() != 20) throw std::runtime_error("invalid size of target id");
std::copy(target.begin(), target.end(), m.info_hash.begin()); std::copy(target.begin(), target.end(), m.info_hash.begin());
#ifdef TORRENT_DHT_VERBOSE_LOGGING #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 #endif
m.message_id = libtorrent::dht::messages::find_node; m.message_id = libtorrent::dht::messages::find_node;

View file

@ -91,9 +91,9 @@ void purge_peers(std::set<peer_entry>& peers)
void nop() {} void nop() {}
node_impl::node_impl(boost::function<void(msg const&)> const& f 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_settings(settings)
, m_id(node_id ? *node_id : generate_id()) , m_id(generate_id())
, m_table(m_id, 8, settings) , m_table(m_id, 8, settings)
, m_rpc(bind(&node_impl::incoming_request, this, _1) , m_rpc(bind(&node_impl::incoming_request, this, _1)
, m_id, m_table, f) , m_id, m_table, f)

View file

@ -572,6 +572,50 @@ namespace libtorrent
#endif #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) void peer_connection::fast_reconnect(bool r)
{ {
if (!peer_info_struct() || peer_info_struct()->fast_reconnects > 1) if (!peer_info_struct() || peer_info_struct()->fast_reconnects > 1)
@ -1129,6 +1173,8 @@ namespace libtorrent
<< " <== HAVE [ piece: " << index << "]\n"; << " <== HAVE [ piece: " << index << "]\n";
#endif #endif
if (is_disconnecting()) return;
if (!t->valid_metadata() && index > int(m_have_piece.size())) if (!t->valid_metadata() && index > int(m_have_piece.size()))
{ {
if (index < 65536) if (index < 65536)
@ -1343,6 +1389,7 @@ namespace libtorrent
// if we haven't received a bitfield, it was // if we haven't received a bitfield, it was
// probably omitted, which is the same as 'have_none' // probably omitted, which is the same as 'have_none'
if (!m_bitfield_received) incoming_have_none(); if (!m_bitfield_received) incoming_have_none();
if (is_disconnecting()) return;
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
for (extension_list_t::iterator i = m_extensions.begin() for (extension_list_t::iterator i = m_extensions.begin()
@ -1549,6 +1596,7 @@ namespace libtorrent
// if we haven't received a bitfield, it was // if we haven't received a bitfield, it was
// probably omitted, which is the same as 'have_none' // probably omitted, which is the same as 'have_none'
if (!m_bitfield_received) incoming_have_none(); if (!m_bitfield_received) incoming_have_none();
if (is_disconnecting()) return;
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
for (extension_list_t::iterator i = m_extensions.begin() for (extension_list_t::iterator i = m_extensions.begin()
@ -1572,7 +1620,7 @@ namespace libtorrent
"s: " << p.start << " | " "s: " << p.start << " | "
"l: " << p.length << " | " "l: " << p.length << " | "
"ds: " << statistics().download_rate() << " | " "ds: " << statistics().download_rate() << " | "
"qs: " << m_desired_queue_size << " ]\n"; "qs: " << int(m_desired_queue_size) << " ]\n";
#endif #endif
if (p.length == 0) if (p.length == 0)
@ -1639,7 +1687,7 @@ namespace libtorrent
return; 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) for (int i = 0; i < block_index; ++i)
{ {
pending_block& qe = m_download_queue[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() m_ses.m_alerts.post_alert(request_dropped_alert(t->get_handle()
, remote(), pid(), qe.block.block_index, qe.block.piece_index)); , remote(), pid(), qe.block.block_index, qe.block.piece_index));
picker.abort_download(qe.block); picker.abort_download(qe.block);
TORRENT_ASSERT(m_download_queue.begin() + i != b);
m_download_queue.erase(m_download_queue.begin() + i); m_download_queue.erase(m_download_queue.begin() + i);
--i; --i;
--block_index; --block_index;
@ -1723,9 +1772,12 @@ namespace libtorrent
bool multi = picker.num_peers(block_finished) > 1; bool multi = picker.num_peers(block_finished) > 1;
picker.mark_as_writing(block_finished, peer_info_struct()); 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 we requested this block from other peers, cancel it now
if (multi) t->cancel_block(block_finished); if (multi) t->cancel_block(block_finished);
TORRENT_ASSERT(picker.num_peers(block_finished) == 0);
#if !defined NDEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS #if !defined NDEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS
t->check_invariant(); t->check_invariant();
#endif #endif
@ -1776,6 +1828,7 @@ namespace libtorrent
TORRENT_ASSERT(p.piece == j.piece); TORRENT_ASSERT(p.piece == j.piece);
TORRENT_ASSERT(p.start == j.offset); TORRENT_ASSERT(p.start == j.offset);
TORRENT_ASSERT(picker.num_peers(block_finished) == 0);
picker.mark_as_finished(block_finished, peer_info_struct()); picker.mark_as_finished(block_finished, peer_info_struct());
if (t->alerts().should_post<block_finished_alert>()) if (t->alerts().should_post<block_finished_alert>())
{ {
@ -2332,7 +2385,7 @@ namespace libtorrent
"s: " << r.start << " | " "s: " << r.start << " | "
"l: " << r.length << " | " "l: " << r.length << " | "
"ds: " << statistics().download_rate() << " B/s | " "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"; "blk: " << (m_request_large_blocks?"large":"single") << " ]\n";
#endif #endif
} }
@ -3898,7 +3951,7 @@ namespace libtorrent
m_speed = medium; m_speed = medium;
else if (download_rate < torrent_download_rate / 15 && m_speed == fast) else if (download_rate < torrent_download_rate / 15 && m_speed == fast)
m_speed = medium; m_speed = medium;
else if (download_rate < torrent_download_rate / 63 && m_speed == medium) else
m_speed = slow; m_speed = slow;
return m_speed; return m_speed;

File diff suppressed because it is too large Load diff

View file

@ -200,8 +200,6 @@ namespace libtorrent
int prefer_whole_pieces = c.prefer_whole_pieces(); int prefer_whole_pieces = c.prefer_whole_pieces();
bool rarest_first = t.num_have() >= t.settings().initial_picker_threshold;
if (prefer_whole_pieces == 0) if (prefer_whole_pieces == 0)
{ {
prefer_whole_pieces = c.statistics().download_payload_rate() prefer_whole_pieces = c.statistics().download_payload_rate()
@ -250,7 +248,7 @@ namespace libtorrent
p.pick_pieces(mask, interesting_pieces p.pick_pieces(mask, interesting_pieces
, num_requests, prefer_whole_pieces, c.peer_info_struct() , num_requests, prefer_whole_pieces, c.peer_info_struct()
, state, rarest_first, c.on_parole(), suggested); , state, c.picker_options(), suggested);
} }
else else
{ {
@ -264,7 +262,7 @@ namespace libtorrent
// then use this mode. // then use this mode.
p.pick_pieces(bits, interesting_pieces p.pick_pieces(bits, interesting_pieces
, num_requests, prefer_whole_pieces, c.peer_info_struct() , 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 #ifdef TORRENT_VERBOSE_LOGGING
@ -303,10 +301,6 @@ namespace libtorrent
if (busy_pieces.empty() || num_requests <= 0) 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; return;
} }

View file

@ -1494,6 +1494,8 @@ namespace aux {
} }
} }
if (m_allowed_upload_slots > 0)
{
m_optimistic_unchoke_time_scaler--; m_optimistic_unchoke_time_scaler--;
if (m_optimistic_unchoke_time_scaler <= 0) if (m_optimistic_unchoke_time_scaler <= 0)
{ {
@ -1528,7 +1530,8 @@ namespace aux {
&& !p->is_disconnecting() && !p->is_disconnecting()
&& p->is_peer_interested() && p->is_peer_interested()
&& t->free_upload_slots() && t->free_upload_slots()
&& p->is_choked()) && p->is_choked()
&& t->valid_metadata())
{ {
last_unchoke = pi->last_optimistically_unchoked; last_unchoke = pi->last_optimistically_unchoked;
optimistic_unchoke_candidate = i; optimistic_unchoke_candidate = i;
@ -1558,6 +1561,7 @@ namespace aux {
} }
} }
} }
}
void session_impl::operator()() void session_impl::operator()()
{ {
@ -2046,11 +2050,20 @@ namespace aux {
, m_dht_settings.service_port , m_dht_settings.service_port
, 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) 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); 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() void session_impl::stop_dht()
@ -2114,9 +2127,10 @@ namespace aux {
void session_impl::add_dht_router(std::pair<std::string, int> const& node) 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); 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 #endif
@ -2167,7 +2181,7 @@ namespace aux {
void session_impl::set_max_uploads(int limit) 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); mutex_t::scoped_lock l(m_mutex);
INVARIANT_CHECK; INVARIANT_CHECK;

View file

@ -754,10 +754,14 @@ namespace libtorrent
m_progress = j.piece / float(torrent_file().num_pieces()); m_progress = j.piece / float(torrent_file().num_pieces());
m_picker->check_invariant();
TORRENT_ASSERT(m_picker); TORRENT_ASSERT(m_picker);
if (j.offset >= 0 && !m_picker->have_piece(j.offset)) if (j.offset >= 0 && !m_picker->have_piece(j.offset))
m_picker->we_have(j.offset); m_picker->we_have(j.offset);
m_picker->check_invariant();
// we're not done checking yet // we're not done checking yet
// this handler will be called repeatedly until // this handler will be called repeatedly until
// we're done, or encounter a failure // we're done, or encounter a failure
@ -3298,9 +3302,6 @@ namespace libtorrent
if (!is_seed()) 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 // if we just finished checking and we're not a seed, we are
// likely to be unpaused // likely to be unpaused
if (m_ses.m_auto_manage_time_scaler > 1) if (m_ses.m_auto_manage_time_scaler > 1)
@ -3549,13 +3550,7 @@ namespace libtorrent
#endif #endif
void torrent::set_sequential_download(bool sd) void torrent::set_sequential_download(bool sd)
{ { m_sequential_download = sd; }
m_sequential_download = sd;
if (has_picker())
{
picker().sequential_download(sd);
}
}
void torrent::set_queue_position(int p) void torrent::set_queue_position(int p)
{ {

View file

@ -499,6 +499,12 @@ namespace libtorrent
TORRENT_FORWARD(replace_trackers(urls)); 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 torrent_info const& torrent_handle::get_torrent_info() const
{ {
INVARIANT_CHECK; INVARIANT_CHECK;

View file

@ -229,6 +229,7 @@ namespace libtorrent
boost::shared_ptr<request_callback> cb = con->requester(); boost::shared_ptr<request_callback> cb = con->requester();
if (cb) cb->m_manager = this; if (cb) cb->m_manager = this;
con->start();
} }
void tracker_manager::abort_all_requests() void tracker_manager::abort_all_requests()

View file

@ -93,14 +93,17 @@ namespace libtorrent
, m_state(action_error) , m_state(action_error)
{ {
m_socket.set_proxy_settings(proxy); m_socket.set_proxy_settings(proxy);
}
void udp_tracker_connection::start()
{
std::string hostname; std::string hostname;
int port; int port;
char const* error; char const* error;
using boost::tuples::ignore; using boost::tuples::ignore;
boost::tie(ignore, ignore, hostname, port, ignore, error) boost::tie(ignore, ignore, hostname, port, ignore, error)
= parse_url_components(req.url); = parse_url_components(tracker_req().url);
if (error) if (error)
{ {
@ -112,7 +115,7 @@ namespace libtorrent
m_name_lookup.async_resolve(q m_name_lookup.async_resolve(q
, boost::bind( , boost::bind(
&udp_tracker_connection::name_lookup, self(), _1, _2)); &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.stop_tracker_timeout
: m_settings.tracker_completion_timeout : m_settings.tracker_completion_timeout
, m_settings.tracker_receive_timeout); , m_settings.tracker_receive_timeout);