lt sync 2667

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

View File

@ -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

View File

@ -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;
};
}

View File

@ -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);

View File

@ -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(); }

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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; }

View File

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

View File

@ -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();
}

View File

@ -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;

View File

@ -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)

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>
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;

View File

@ -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)

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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)
{

View File

@ -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;

View File

@ -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()

View File

@ -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);