diff --git a/ChangeLog b/ChangeLog
index 438f50287..17fbe3339 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,10 +1,14 @@
- * Added the possibility to have libtorrent resolve the countries of
+ * fixed a bug in the DHT which could be triggered if the network was
+ dropped or extremely rare cases.
+ * if the download rate is limited, web seeds will now only use left-over
+ bandwidth after all bt peers have used up as much bandwidth as they can.
+ * added the possibility to have libtorrent resolve the countries of
the peers in torrents.
- * Improved the bandwidth limiter (it now implements a leaky bucket).
- * Improved the HTTP seed downloader to report accurate progress.
- * Added more client peer-id signatures to be recognized.
+ * improved the bandwidth limiter (it now implements a leaky bucket/node bucket).
+ * improved the HTTP seed downloader to report accurate progress.
+ * added more client peer-id signatures to be recognized.
* added support for HTTP servers that skip the CR before the NL at line breaks.
- * fixed bug in the HTTP code that onlcy accepted headers case sensitive.
+ * fixed bug in the HTTP code that only accepted headers case sensitive.
* fixed bug where one of the session constructors didn't initialize boost.filesystem.
* fixed bug when the initial checking of a torrent fails with an exception.
* fixed bug in DHT code which would send incorrect announce messages.
diff --git a/docs/manual.html b/docs/manual.html
index c5fb04aab..c71e89f17 100755
--- a/docs/manual.html
+++ b/docs/manual.html
@@ -2505,16 +2505,22 @@ struct tracker_alert: torrent_alert
This alert is only for informational purpose. It is generated when a tracker announce
-succeeds. It is generated with severity level info.
+succeeds. It is generated regardless what kind of tracker was used, be it UDP, HTTP or
+the DHT. It is generated with severity level
info.
struct tracker_reply_alert: torrent_alert
{
tracker_reply_alert(const torrent_handle& h
+ , int num_peers
, const std::string& msg);
+ int num_peers;
+
virtual std::auto_ptr<alert> clone() const;
};
+
The num_peers tells how many peers were returned from the tracker. This is
+not necessarily all new peers, some of them may already be connected.
diff --git a/docs/manual.rst b/docs/manual.rst
index efa2757ca..0f4441ee5 100755
--- a/docs/manual.rst
+++ b/docs/manual.rst
@@ -2558,17 +2558,24 @@ tracker_reply_alert
-------------------
This alert is only for informational purpose. It is generated when a tracker announce
-succeeds. It is generated with severity level ``info``.
+succeeds. It is generated regardless what kind of tracker was used, be it UDP, HTTP or
+the DHT. It is generated with severity level ``info``.
::
struct tracker_reply_alert: torrent_alert
{
tracker_reply_alert(const torrent_handle& h
+ , int num_peers
, const std::string& msg);
+ int num_peers;
+
virtual std::auto_ptr
clone() const;
};
+
+The ``num_peers`` tells how many peers were returned from the tracker. This is
+not necessarily all new peers, some of them may already be connected.
tracker_warning_alert
---------------------
diff --git a/examples/client_test.cpp b/examples/client_test.cpp
index 94d085246..29afe0263 100755
--- a/examples/client_test.cpp
+++ b/examples/client_test.cpp
@@ -806,6 +806,11 @@ int main(int ac, char* av[])
{
events.push_back(now + ": tracker message: " + p->msg());
}
+ else if (tracker_reply_alert* p = dynamic_cast(a.get()))
+ {
+ events.push_back(now + ": " + p->msg() + " ("
+ + boost::lexical_cast(p->num_peers) + ")");
+ }
else
{
events.push_back(now + ": " + a->msg());
diff --git a/include/libtorrent/alert_types.hpp b/include/libtorrent/alert_types.hpp
index 6f1075a6a..c9127c5c4 100755
--- a/include/libtorrent/alert_types.hpp
+++ b/include/libtorrent/alert_types.hpp
@@ -86,10 +86,14 @@ namespace libtorrent
struct TORRENT_EXPORT tracker_reply_alert: torrent_alert
{
tracker_reply_alert(torrent_handle const& h
+ , int np
, std::string const& msg)
: torrent_alert(h, alert::info, msg)
+ , num_peers(np)
{}
+ int num_peers;
+
virtual std::auto_ptr clone() const
{ return std::auto_ptr(new tracker_reply_alert(*this)); }
};
diff --git a/include/libtorrent/bandwidth_manager.hpp b/include/libtorrent/bandwidth_manager.hpp
index 9b9258d5b..e91759616 100644
--- a/include/libtorrent/bandwidth_manager.hpp
+++ b/include/libtorrent/bandwidth_manager.hpp
@@ -77,6 +77,13 @@ struct history_entry
weak_ptr tor;
};
+struct bw_queue_entry
+{
+ bw_queue_entry(boost::intrusive_ptr const& pe, bool no_prio);
+ boost::intrusive_ptr peer;
+ bool non_prioritized;
+};
+
// member of peer_connection
struct bandwidth_limit
{
@@ -169,7 +176,11 @@ struct bandwidth_manager
return m_limit;
}
- void request_bandwidth(intrusive_ptr peer);
+ // non prioritized means that, if there's a line for bandwidth,
+ // others will cut in front of the non-prioritized peers.
+ // this is used by web seeds
+ void request_bandwidth(intrusive_ptr peer
+ , bool non_prioritized);
#ifndef NDEBUG
void check_invariant() const;
@@ -202,7 +213,7 @@ private:
int m_current_quota;
// these are the consumers that want bandwidth
- std::deque > m_queue;
+ std::deque m_queue;
// these are the consumers that have received bandwidth
// that will expire
diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp
index d4677546d..60182dadf 100755
--- a/include/libtorrent/peer_connection.hpp
+++ b/include/libtorrent/peer_connection.hpp
@@ -156,6 +156,9 @@ namespace libtorrent
void request_large_blocks(bool b)
{ m_request_large_blocks = b; }
+ void set_non_prioritized(bool b)
+ { m_non_prioritized = b; }
+
// this adds an announcement in the announcement queue
// it will let the peer know that we have the given piece
void announce_piece(int index);
@@ -611,6 +614,12 @@ namespace libtorrent
// the http-downloader, to request whole pieces
// at a time.
bool m_request_large_blocks;
+
+ // if this is true, other (prioritized) peers will
+ // skip ahead of it in the queue for bandwidth. The
+ // effect is that non prioritized peers will only use
+ // the left-over bandwidth (suitable for web seeds).
+ bool m_non_prioritized;
// reference counter for intrusive_ptr
mutable boost::detail::atomic_count m_refs;
diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp
index 4bdfab0e7..d1aa40632 100755
--- a/include/libtorrent/torrent.hpp
+++ b/include/libtorrent/torrent.hpp
@@ -201,7 +201,8 @@ namespace libtorrent
bandwidth_limit m_bandwidth_limit[2];
void request_bandwidth(int channel
- , boost::intrusive_ptr p);
+ , boost::intrusive_ptr p
+ , bool non_prioritized);
void expire_bandwidth(int channel, int amount);
void assign_bandwidth(int channel, int amount);
@@ -564,7 +565,7 @@ namespace libtorrent
boost::scoped_ptr m_picker;
// the queue of peer_connections that want more bandwidth
- std::deque > m_bandwidth_queue[2];
+ std::deque m_bandwidth_queue[2];
std::vector m_trackers;
// this is an index into m_torrent_file.trackers()
diff --git a/src/bandwidth_manager.cpp b/src/bandwidth_manager.cpp
index 5ba382c50..59aaeaf9d 100644
--- a/src/bandwidth_manager.cpp
+++ b/src/bandwidth_manager.cpp
@@ -48,6 +48,11 @@ namespace libtorrent
, weak_ptr t, int a, pt::ptime exp)
: expires_at(exp), amount(a), peer(p), tor(t)
{}
+
+ bw_queue_entry::bw_queue_entry(intrusive_ptr const& pe
+ , bool no_prio)
+ : peer(pe), non_prioritized(no_prio)
+ {}
bandwidth_manager::bandwidth_manager(io_service& ios, int channel)
: m_ios(ios)
@@ -57,23 +62,39 @@ namespace libtorrent
, m_channel(channel)
{}
- void bandwidth_manager::request_bandwidth(intrusive_ptr peer)
+ void bandwidth_manager::request_bandwidth(intrusive_ptr peer
+ , bool non_prioritized)
{
INVARIANT_CHECK;
// make sure this peer isn't already in line
// waiting for bandwidth
#ifndef NDEBUG
- for (std::deque >::iterator i = m_queue.begin()
+ for (std::deque::iterator i = m_queue.begin()
, end(m_queue.end()); i != end; ++i)
{
- assert(*i < peer || peer < *i);
+ assert(i->peer < peer || peer < i->peer);
}
#endif
assert(peer->max_assignable_bandwidth(m_channel) > 0);
-
- m_queue.push_back(peer);
+
+ // if the queue is empty, we have to push the new
+ // peer at the back of it. If the peer is non-prioritized
+ // it is not supposed to cut in fron of anybody, so then
+ // we also just add it at the end
+ if (m_queue.empty() || non_prioritized)
+ {
+ m_queue.push_back(bw_queue_entry(peer, non_prioritized));
+ }
+ else
+ {
+ // skip forward in the queue until we find a prioritized peer
+ // or hit the front of it.
+ std::deque::reverse_iterator i = m_queue.rbegin();
+ while (i != m_queue.rend() && i->non_prioritized) ++i;
+ m_queue.insert(i.base(), bw_queue_entry(peer, non_prioritized));
+ }
if (m_queue.size() == 1) hand_out_bandwidth();
}
@@ -176,12 +197,12 @@ namespace libtorrent
while (!m_queue.empty() && amount > 0)
{
assert(amount == limit - m_current_quota);
- intrusive_ptr peer = m_queue.front();
+ bw_queue_entry qe = m_queue.front();
m_queue.pop_front();
- shared_ptr t = peer->associated_torrent().lock();
+ shared_ptr t = qe.peer->associated_torrent().lock();
if (!t) continue;
- if (peer->is_disconnecting())
+ if (qe.peer->is_disconnecting())
{
t->expire_bandwidth(m_channel, -1);
continue;
@@ -191,7 +212,7 @@ namespace libtorrent
// the bandwidth quota is subtracted once the data has been
// send. If the peer was added to the queue while the data was
// still being sent, max_assignable may have been > 0 at that time.
- int max_assignable = peer->max_assignable_bandwidth(m_channel);
+ int max_assignable = qe.peer->max_assignable_bandwidth(m_channel);
if (max_assignable == 0)
{
t->expire_bandwidth(m_channel, -1);
@@ -206,9 +227,9 @@ namespace libtorrent
, max_assignable));
assert(single_amount > 0);
amount -= single_amount;
- peer->assign_bandwidth(m_channel, single_amount);
+ qe.peer->assign_bandwidth(m_channel, single_amount);
t->assign_bandwidth(m_channel, single_amount);
- add_history_entry(history_entry(peer, t, single_amount, now + window_size));
+ add_history_entry(history_entry(qe.peer, t, single_amount, now + window_size));
}
}
catch (std::exception& e)
diff --git a/src/http_tracker_connection.cpp b/src/http_tracker_connection.cpp
index 6c6b19e0f..5e6e6ecbe 100755
--- a/src/http_tracker_connection.cpp
+++ b/src/http_tracker_connection.cpp
@@ -641,6 +641,13 @@ namespace libtorrent
fail(-1, error_str.c_str());
return;
}
+
+ // if the protocol isn't specified, assume http
+ if (location.compare(0, 7, "http://") != 0
+ && location.compare(0, 6, "udp://") != 0)
+ {
+ location.insert(0, "http://");
+ }
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
if (has_requester()) requester().debug_log("Redirecting to \"" + location + "\"");
diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp
index 39cb5119f..7bf1d0b4b 100755
--- a/src/peer_connection.cpp
+++ b/src/peer_connection.cpp
@@ -116,6 +116,7 @@ namespace libtorrent
, m_reading(false)
, m_prefer_whole_pieces(false)
, m_request_large_blocks(false)
+ , m_non_prioritized(false)
, m_refs(0)
, m_upload_limit(resource_request::inf)
, m_download_limit(resource_request::inf)
@@ -179,6 +180,7 @@ namespace libtorrent
, m_reading(false)
, m_prefer_whole_pieces(false)
, m_request_large_blocks(false)
+ , m_non_prioritized(false)
, m_refs(0)
, m_upload_limit(resource_request::inf)
, m_download_limit(resource_request::inf)
@@ -1760,7 +1762,7 @@ namespace libtorrent
(*m_logger) << "req bandwidth [ " << upload_channel << " ]\n";
#endif
- t->request_bandwidth(upload_channel, self());
+ t->request_bandwidth(upload_channel, self(), m_non_prioritized);
m_writing = true;
}
return;
@@ -1817,7 +1819,7 @@ namespace libtorrent
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << "req bandwidth [ " << download_channel << " ]\n";
#endif
- t->request_bandwidth(download_channel, self());
+ t->request_bandwidth(download_channel, self(), m_non_prioritized);
m_reading = true;
}
return;
diff --git a/src/torrent.cpp b/src/torrent.cpp
index 695c2feca..ddadf0e49 100755
--- a/src/torrent.cpp
+++ b/src/torrent.cpp
@@ -479,6 +479,13 @@ namespace libtorrent
void torrent::on_dht_announce_response(std::vector const& peers)
{
+ if (peers.empty()) return;
+
+ if (m_ses.m_alerts.should_post(alert::info))
+ {
+ m_ses.m_alerts.post_alert(tracker_reply_alert(
+ get_handle(), peers.size(), "Got peers from DHT"));
+ }
std::for_each(peers.begin(), peers.end(), bind(
&policy::peer_from_tracker, boost::ref(m_policy), _1, peer_id(0)));
}
@@ -583,7 +590,7 @@ namespace libtorrent
s << "Got response from tracker: "
<< m_trackers[m_last_working_tracker].url;
m_ses.m_alerts.post_alert(tracker_reply_alert(
- get_handle(), s.str()));
+ get_handle(), peer_list.size(), s.str()));
}
m_got_tracker_response = true;
}
@@ -1773,19 +1780,20 @@ namespace libtorrent
}
void torrent::request_bandwidth(int channel
- , boost::intrusive_ptr p)
+ , boost::intrusive_ptr p
+ , bool non_prioritized)
{
if (m_bandwidth_limit[channel].max_assignable() >= max_bandwidth_block_size)
{
if (channel == peer_connection::upload_channel)
- m_ses.m_ul_bandwidth_manager.request_bandwidth(p);
+ m_ses.m_ul_bandwidth_manager.request_bandwidth(p, non_prioritized);
else if (channel == peer_connection::download_channel)
- m_ses.m_dl_bandwidth_manager.request_bandwidth(p);
+ m_ses.m_dl_bandwidth_manager.request_bandwidth(p, non_prioritized);
m_bandwidth_limit[channel].assign(max_bandwidth_block_size);
}
else
{
- m_bandwidth_queue[channel].push_back(p);
+ m_bandwidth_queue[channel].push_back(bw_queue_entry(p, non_prioritized));
}
}
@@ -1800,12 +1808,12 @@ namespace libtorrent
while (!m_bandwidth_queue[channel].empty()
&& m_bandwidth_limit[channel].max_assignable() >= max_bandwidth_block_size)
{
- intrusive_ptr p = m_bandwidth_queue[channel].front();
+ bw_queue_entry qe = m_bandwidth_queue[channel].front();
m_bandwidth_queue[channel].pop_front();
if (channel == peer_connection::upload_channel)
- m_ses.m_ul_bandwidth_manager.request_bandwidth(p);
+ m_ses.m_ul_bandwidth_manager.request_bandwidth(qe.peer, qe.non_prioritized);
else if (channel == peer_connection::download_channel)
- m_ses.m_dl_bandwidth_manager.request_bandwidth(p);
+ m_ses.m_dl_bandwidth_manager.request_bandwidth(qe.peer, qe.non_prioritized);
m_bandwidth_limit[channel].assign(max_bandwidth_block_size);
}
}
diff --git a/src/web_peer_connection.cpp b/src/web_peer_connection.cpp
index bb9d20991..4d1b4c565 100755
--- a/src/web_peer_connection.cpp
+++ b/src/web_peer_connection.cpp
@@ -70,7 +70,11 @@ namespace libtorrent
// we always prefer downloading entire
// pieces from web seeds
prefer_whole_pieces(true);
+ // we want large blocks as well, so
+ // we can request more bytes at once
request_large_blocks(true);
+ // we only want left-over bandwidth
+ set_non_prioritized(true);
shared_ptr tor = t.lock();
assert(tor);
int blocks_per_piece = tor->torrent_file().piece_length() / tor->block_size();