added tracker exchange (tex) extension
This commit is contained in:
parent
1b686a1364
commit
acbdbfc1ef
1
Jamfile
1
Jamfile
|
@ -336,6 +336,7 @@ SOURCES =
|
|||
metadata_transfer
|
||||
ut_pex
|
||||
ut_metadata
|
||||
lt_trackers
|
||||
smart_ban
|
||||
;
|
||||
|
||||
|
|
|
@ -1480,9 +1480,13 @@ ones with lower tier will always be tried before the one with higher tier number
|
|||
{
|
||||
announce_entry(std::string const& url);
|
||||
std::string url;
|
||||
int tier;
|
||||
boost::uint8_t tier;
|
||||
boost::uint8_t fail_limit;
|
||||
};
|
||||
|
||||
``fail_limit`` is the max number of failures to announce to this tracker in
|
||||
a row, before this tracker is not used anymore.
|
||||
|
||||
|
||||
total_size() piece_length() piece_size() num_pieces()
|
||||
-----------------------------------------------------
|
||||
|
|
|
@ -1348,7 +1348,7 @@ int main(int ac, char* av[])
|
|||
<< std::hex << s.seed_rank << std::dec << " "
|
||||
<< s.last_scrape << "\n" << esc("0");
|
||||
|
||||
if (torrent_index != active_torrent) continue;
|
||||
if (torrent_index != active_torrent && s.state != torrent_status::seeding) continue;
|
||||
char const* progress_bar_color = "33"; // yellow
|
||||
if (s.state == torrent_status::checking_files
|
||||
|| s.state == torrent_status::downloading_metadata)
|
||||
|
|
|
@ -84,6 +84,7 @@ libtorrent/aux_/session_impl.hpp \
|
|||
libtorrent/extensions/metadata_transfer.hpp \
|
||||
libtorrent/extensions/ut_pex.hpp \
|
||||
libtorrent/extensions/ut_metadata.hpp \
|
||||
libtorrent/extensions/lt_trackers.hpp \
|
||||
libtorrent/extensions/logger.hpp \
|
||||
libtorrent/extensions/smart_ban.hpp \
|
||||
\
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2008, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TORRENT_LT_TRACKERS_HPP_INCLUDED
|
||||
#define TORRENT_LT_TRACKERS_HPP_INCLUDED
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 1)
|
||||
#endif
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include "libtorrent/config.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
struct torrent_plugin;
|
||||
class torrent;
|
||||
TORRENT_EXPORT boost::shared_ptr<torrent_plugin> create_lt_trackers_plugin(torrent*, void*);
|
||||
}
|
||||
|
||||
#endif // TORRENT_LT_TRACKERS_HPP_INCLUDED
|
||||
|
|
@ -95,6 +95,7 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(len > 0);
|
||||
SHA1_Update(&m_context, reinterpret_cast<unsigned char const*>(data), len);
|
||||
}
|
||||
void update(std::string const& data) { update(&data[0], data.size()); }
|
||||
void update(const char* data, int len)
|
||||
{
|
||||
TORRENT_ASSERT(data != 0);
|
||||
|
|
|
@ -68,9 +68,27 @@ namespace libtorrent
|
|||
|
||||
struct TORRENT_EXPORT announce_entry
|
||||
{
|
||||
announce_entry(std::string const& u): url(u), tier(0) {}
|
||||
announce_entry(std::string const& u)
|
||||
: url(u), tier(0)
|
||||
, fail_limit(3), fails(0)
|
||||
, verified(false)
|
||||
{}
|
||||
|
||||
std::string url;
|
||||
int tier;
|
||||
boost::uint8_t tier;
|
||||
// the number of times this tracker can fail
|
||||
// in a row before it's removed. 0 means unlimited
|
||||
boost::uint8_t fail_limit;
|
||||
|
||||
// the number of times in a row this tracker has failed
|
||||
boost::uint8_t fails;
|
||||
|
||||
// is set to true if we have ever received a response from
|
||||
// this tracker
|
||||
bool verified:1;
|
||||
|
||||
bool can_announce() const
|
||||
{ return fails < fail_limit || fail_limit == 0; }
|
||||
};
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
|
|
|
@ -22,7 +22,7 @@ http_tracker_connection.cpp udp_tracker_connection.cpp \
|
|||
alert.cpp identify_client.cpp ip_filter.cpp file.cpp metadata_transfer.cpp \
|
||||
logger.cpp file_pool.cpp ut_pex.cpp lsd.cpp upnp.cpp instantiate_connection.cpp \
|
||||
socks5_stream.cpp socks4_stream.cpp http_stream.cpp connection_queue.cpp \
|
||||
disk_io_thread.cpp ut_metadata.cpp magnet_uri.cpp udp_socket.cpp smart_ban.cpp \
|
||||
disk_io_thread.cpp ut_metadata.cpp lt_trackers.cpp magnet_uri.cpp udp_socket.cpp smart_ban.cpp \
|
||||
http_parser.cpp gzip.cpp disk_buffer_holder.cpp create_torrent.cpp GeoIP.c \
|
||||
parse_url.cpp file_storage.cpp error_code.cpp ConvertUTF.cpp $(kademlia_sources)
|
||||
# mapped_storage.cpp
|
||||
|
|
|
@ -0,0 +1,347 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2008, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "libtorrent/pch.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 1)
|
||||
#endif
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <numeric>
|
||||
#include <cstdio>
|
||||
|
||||
#include "libtorrent/peer_connection.hpp"
|
||||
#include "libtorrent/bt_peer_connection.hpp"
|
||||
#include "libtorrent/hasher.hpp"
|
||||
#include "libtorrent/bencode.hpp"
|
||||
#include "libtorrent/torrent.hpp"
|
||||
#include "libtorrent/extensions.hpp"
|
||||
#include "libtorrent/extensions/ut_metadata.hpp"
|
||||
#include "libtorrent/alert_types.hpp"
|
||||
#ifdef TORRENT_STATS
|
||||
#include "libtorrent/aux_/session_impl.hpp"
|
||||
#endif
|
||||
|
||||
namespace libtorrent { namespace
|
||||
{
|
||||
|
||||
bool send_tracker(announce_entry const& e)
|
||||
{
|
||||
// max_fails == 0 means that it's one
|
||||
// of the trackers from the trackers
|
||||
// from the torrent file
|
||||
return e.fail_limit == 0 || e.verified;
|
||||
}
|
||||
|
||||
struct lt_tracker_plugin : torrent_plugin
|
||||
{
|
||||
lt_tracker_plugin(torrent& t)
|
||||
: m_torrent(t)
|
||||
, m_updates(0)
|
||||
, m_2_minutes(110)
|
||||
{
|
||||
m_old_trackers = t.trackers();
|
||||
update_list_hash();
|
||||
}
|
||||
|
||||
virtual boost::shared_ptr<peer_plugin> new_connection(
|
||||
peer_connection* pc);
|
||||
|
||||
virtual void tick()
|
||||
{
|
||||
if (m_2_minutes++ < 120) return;
|
||||
m_2_minutes = 0;
|
||||
|
||||
// build tracker diff
|
||||
entry tex;
|
||||
entry::list_type& added = tex["added"].list();
|
||||
std::vector<announce_entry> const& trackers = m_torrent.trackers();
|
||||
for (std::vector<announce_entry>::const_iterator i = trackers.begin()
|
||||
, end(trackers.end()); i != end; ++i)
|
||||
{
|
||||
std::vector<announce_entry>::const_iterator k = std::find_if(
|
||||
m_old_trackers.begin(), m_old_trackers.end()
|
||||
, boost::bind(&announce_entry::url, _1) == i->url);
|
||||
if (k != m_old_trackers.end()) continue;
|
||||
if (!send_tracker(*i)) continue;
|
||||
m_old_trackers.push_back(*i);
|
||||
++m_updates;
|
||||
added.push_back(i->url);
|
||||
}
|
||||
m_lt_trackers_msg.clear();
|
||||
bencode(std::back_inserter(m_lt_trackers_msg), tex);
|
||||
if (m_updates > 0) update_list_hash();
|
||||
}
|
||||
|
||||
void update_list_hash()
|
||||
{
|
||||
std::vector<std::string> canonical_list;
|
||||
std::transform(m_old_trackers.begin(), m_old_trackers.end(), back_inserter(canonical_list)
|
||||
, boost::bind(&announce_entry::url, _1));
|
||||
std::sort(canonical_list.begin(), canonical_list.end());
|
||||
|
||||
hasher h;
|
||||
std::for_each(canonical_list.begin(), canonical_list.end()
|
||||
, boost::bind(&hasher::update, &h, _1));
|
||||
m_list_hash = h.final();
|
||||
}
|
||||
|
||||
int num_updates() const { return m_updates; }
|
||||
|
||||
std::vector<char> const& get_lt_tex_msg() const { return m_lt_trackers_msg; }
|
||||
|
||||
sha1_hash const& list_hash() const { return m_list_hash; }
|
||||
|
||||
std::vector<announce_entry> const& trackers() const { return m_old_trackers; }
|
||||
|
||||
private:
|
||||
torrent& m_torrent;
|
||||
std::vector<announce_entry> m_old_trackers;
|
||||
int m_updates;
|
||||
int m_2_minutes;
|
||||
std::vector<char> m_lt_trackers_msg;
|
||||
sha1_hash m_list_hash;
|
||||
};
|
||||
|
||||
|
||||
struct lt_tracker_peer_plugin : peer_plugin
|
||||
{
|
||||
lt_tracker_peer_plugin(torrent& t, bt_peer_connection& pc, lt_tracker_plugin& tp)
|
||||
: m_message_index(0)
|
||||
, m_torrent(t)
|
||||
, m_pc(pc)
|
||||
, m_tp(tp)
|
||||
, m_2_minutes(115)
|
||||
, m_full_list(true)
|
||||
{}
|
||||
|
||||
// can add entries to the extension handshake
|
||||
virtual void add_handshake(entry& h)
|
||||
{
|
||||
entry& messages = h["m"];
|
||||
messages["lt_tex"] = 3;
|
||||
h["tr"] = m_tp.list_hash().to_string();
|
||||
}
|
||||
|
||||
// called when the extension handshake from the other end is received
|
||||
virtual bool on_extension_handshake(lazy_entry const& h)
|
||||
{
|
||||
m_message_index = 0;
|
||||
if (h.type() != lazy_entry::dict_t) return false;
|
||||
lazy_entry const* messages = h.dict_find("m");
|
||||
if (!messages || messages->type() != lazy_entry::dict_t) return false;
|
||||
|
||||
int index = messages->dict_find_int_value("lt_tex", -1);
|
||||
if (index == -1) return false;
|
||||
m_message_index = index;
|
||||
|
||||
// if we have the same tracker list, don't bother sending the
|
||||
// full list. Just send deltas
|
||||
std::string tracker_list_hash = h.dict_find_string_value("tr");
|
||||
if (tracker_list_hash.size() == 20
|
||||
&& sha1_hash(tracker_list_hash) == m_tp.list_hash())
|
||||
{
|
||||
m_full_list = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool on_extended(int length
|
||||
, int extended_msg, buffer::const_interval body)
|
||||
{
|
||||
if (extended_msg != 3) return false;
|
||||
if (m_message_index == 0) return false;
|
||||
if (!m_pc.packet_finished()) return true;
|
||||
|
||||
lazy_entry msg;
|
||||
int ret = lazy_bdecode(body.begin, body.end, msg);
|
||||
if (ret != 0 || msg.type() != lazy_entry::dict_t)
|
||||
{
|
||||
m_pc.disconnect("invalid bencoding in lt_tracker message", 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
lazy_entry const* added = msg.dict_find_list("added");
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
std::stringstream log_line;
|
||||
log_line << time_now_string() << " <== LT_TEX [ "
|
||||
"added: ";
|
||||
#endif
|
||||
|
||||
// invalid tex message
|
||||
if (added == 0)
|
||||
{
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_pc.m_logger) << time_now_string() << " <== LT_TEX [ NOT A DICTIONARY ]\n";
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < added->list_size(); ++i)
|
||||
{
|
||||
announce_entry e(added->list_string_value_at(i));
|
||||
if (e.url.empty()) continue;
|
||||
e.fail_limit = 3;
|
||||
m_torrent.add_tracker(e);
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
log_line << e.url << " ";
|
||||
#endif
|
||||
}
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
log_line << "]\n";
|
||||
(*m_pc.m_logger) << log_line.str();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void tick()
|
||||
{
|
||||
if (!m_message_index) return; // no handshake yet
|
||||
if (++m_2_minutes <= 120) return;
|
||||
m_2_minutes = 0;
|
||||
|
||||
if (m_full_list)
|
||||
{
|
||||
send_full_tex_list();
|
||||
m_full_list = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
send_lt_tex_diff();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void send_lt_tex_diff()
|
||||
{
|
||||
// if there's no change in out tracker set, don't send anything
|
||||
if (m_tp.num_updates() == 0) return;
|
||||
|
||||
std::vector<char> const& tex_msg = m_tp.get_lt_tex_msg();
|
||||
|
||||
buffer::interval i = m_pc.allocate_send_buffer(6 + tex_msg.size());
|
||||
|
||||
detail::write_uint32(1 + 1 + tex_msg.size(), i.begin);
|
||||
detail::write_uint8(bt_peer_connection::msg_extended, i.begin);
|
||||
detail::write_uint8(m_message_index, i.begin);
|
||||
std::copy(tex_msg.begin(), tex_msg.end(), i.begin);
|
||||
i.begin += tex_msg.size();
|
||||
|
||||
TORRENT_ASSERT(i.begin == i.end);
|
||||
m_pc.setup_send();
|
||||
}
|
||||
|
||||
void send_full_tex_list() const
|
||||
{
|
||||
if (m_tp.trackers().empty()) return;
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
std::stringstream log_line;
|
||||
log_line << time_now_string() << " ==> LT_TEX [ "
|
||||
"added: ";
|
||||
#endif
|
||||
entry tex;
|
||||
entry::list_type& added = tex["added"].list();
|
||||
for (std::vector<announce_entry>::const_iterator i = m_tp.trackers().begin()
|
||||
, end(m_tp.trackers().end()); i != end; ++i)
|
||||
{
|
||||
if (!send_tracker(*i)) continue;
|
||||
added.push_back(i->url);
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
log_line << i->url << " ";
|
||||
#endif
|
||||
}
|
||||
std::vector<char> tex_msg;
|
||||
bencode(std::back_inserter(tex_msg), tex);
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
log_line << "]\n";
|
||||
(*m_pc.m_logger) << log_line.str();
|
||||
#endif
|
||||
|
||||
buffer::interval i = m_pc.allocate_send_buffer(6 + tex_msg.size());
|
||||
|
||||
detail::write_uint32(1 + 1 + tex_msg.size(), i.begin);
|
||||
detail::write_uint8(bt_peer_connection::msg_extended, i.begin);
|
||||
detail::write_uint8(m_message_index, i.begin);
|
||||
std::copy(tex_msg.begin(), tex_msg.end(), i.begin);
|
||||
i.begin += tex_msg.size();
|
||||
|
||||
TORRENT_ASSERT(i.begin == i.end);
|
||||
m_pc.setup_send();
|
||||
}
|
||||
|
||||
// this is the message index the remote peer uses
|
||||
// for metadata extension messages.
|
||||
int m_message_index;
|
||||
|
||||
torrent& m_torrent;
|
||||
bt_peer_connection& m_pc;
|
||||
lt_tracker_plugin& m_tp;
|
||||
|
||||
int m_2_minutes;
|
||||
bool m_full_list;
|
||||
};
|
||||
|
||||
boost::shared_ptr<peer_plugin> lt_tracker_plugin::new_connection(
|
||||
peer_connection* pc)
|
||||
{
|
||||
bt_peer_connection* c = dynamic_cast<bt_peer_connection*>(pc);
|
||||
if (!c) return boost::shared_ptr<peer_plugin>();
|
||||
return boost::shared_ptr<peer_plugin>(new lt_tracker_peer_plugin(m_torrent, *c, *this));
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
boost::shared_ptr<torrent_plugin> create_lt_trackers_plugin(torrent* t, void*)
|
||||
{
|
||||
if (t->valid_metadata() && t->torrent_file().priv()) return boost::shared_ptr<torrent_plugin>();
|
||||
return boost::shared_ptr<torrent_plugin>(new lt_tracker_plugin(*t));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -310,8 +310,7 @@ namespace libtorrent { namespace
|
|||
// abort if the peer doesn't support the metadata extension
|
||||
if (m_message_index == 0) return;
|
||||
|
||||
// only send metadata if the torrent is non-private
|
||||
if (m_torrent.valid_metadata() && !m_torrent.torrent_file().priv())
|
||||
if (m_torrent.valid_metadata())
|
||||
{
|
||||
std::pair<int, int> offset
|
||||
= req_to_offset(req, (int)m_tp.metadata().left());
|
||||
|
@ -595,6 +594,8 @@ namespace libtorrent
|
|||
|
||||
boost::shared_ptr<torrent_plugin> create_metadata_plugin(torrent* t, void*)
|
||||
{
|
||||
// don't add this extension if the torrent is private
|
||||
if (t->valid_metadata() && t->torrent_file().priv()) return boost::shared_ptr<torrent_plugin>();
|
||||
return boost::shared_ptr<torrent_plugin>(new metadata_plugin(*t));
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include "libtorrent/extensions/ut_pex.hpp"
|
||||
#include "libtorrent/extensions/ut_metadata.hpp"
|
||||
#include "libtorrent/extensions/lt_trackers.hpp"
|
||||
#include "libtorrent/extensions/smart_ban.hpp"
|
||||
#include "libtorrent/peer_id.hpp"
|
||||
#include "libtorrent/torrent_info.hpp"
|
||||
|
@ -148,6 +149,7 @@ namespace libtorrent
|
|||
{
|
||||
add_extension(create_ut_pex_plugin);
|
||||
add_extension(create_ut_metadata_plugin);
|
||||
add_extension(create_lt_trackers_plugin);
|
||||
add_extension(create_smart_ban_plugin);
|
||||
}
|
||||
#endif
|
||||
|
@ -188,6 +190,7 @@ namespace libtorrent
|
|||
{
|
||||
add_extension(create_ut_pex_plugin);
|
||||
add_extension(create_ut_metadata_plugin);
|
||||
add_extension(create_lt_trackers_plugin);
|
||||
add_extension(create_smart_ban_plugin);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -303,6 +303,7 @@ namespace libtorrent
|
|||
if (tracker_url)
|
||||
{
|
||||
m_trackers.push_back(announce_entry(tracker_url));
|
||||
m_trackers.back().fail_limit = 0;
|
||||
m_torrent_file->add_tracker(tracker_url);
|
||||
}
|
||||
}
|
||||
|
@ -945,6 +946,7 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(m_currently_trying_tracker >= 0);
|
||||
TORRENT_ASSERT(m_currently_trying_tracker < int(m_trackers.size()));
|
||||
req.url = m_trackers[m_currently_trying_tracker].url;
|
||||
TORRENT_ASSERT(m_trackers[m_currently_trying_tracker].can_announce());
|
||||
// if we are aborting. we don't want any new peers
|
||||
req.num_want = (req.event == tracker_request::stopped)
|
||||
?0:m_settings.num_want;
|
||||
|
@ -1051,6 +1053,8 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(m_currently_trying_tracker < int(m_trackers.size()));
|
||||
TORRENT_ASSERT(m_trackers[m_currently_trying_tracker].url == r.url);
|
||||
|
||||
m_trackers[m_currently_trying_tracker].verified = true;
|
||||
|
||||
m_last_working_tracker
|
||||
= prioritize_tracker(m_currently_trying_tracker);
|
||||
m_currently_trying_tracker = 0;
|
||||
|
@ -1113,6 +1117,16 @@ namespace libtorrent
|
|||
get_handle(), peer_list.size(), r.url));
|
||||
}
|
||||
m_got_tracker_response = true;
|
||||
|
||||
// when the tracker succeeds, reset the fails-in-a-row counter
|
||||
if (m_currently_trying_tracker != -1)
|
||||
{
|
||||
TORRENT_ASSERT(m_currently_trying_tracker >= 0);
|
||||
TORRENT_ASSERT(m_currently_trying_tracker < int(m_trackers.size()));
|
||||
TORRENT_ASSERT(m_trackers[m_currently_trying_tracker].url == r.url);
|
||||
|
||||
m_trackers[m_currently_trying_tracker].fails = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void torrent::on_peer_name_lookup(error_code const& e, tcp::resolver::iterator host
|
||||
|
@ -3477,7 +3491,8 @@ namespace libtorrent
|
|||
do
|
||||
{
|
||||
++m_currently_trying_tracker;
|
||||
} while (m_currently_trying_tracker < m_trackers.size());
|
||||
} while (m_currently_trying_tracker < m_trackers.size()
|
||||
&& !m_trackers[m_currently_trying_tracker].can_announce());
|
||||
|
||||
if (m_currently_trying_tracker < int(m_trackers.size()))
|
||||
{
|
||||
|
@ -4787,6 +4802,14 @@ namespace libtorrent
|
|||
m_ses.m_alerts.post_alert(tracker_error_alert(get_handle()
|
||||
, m_failed_trackers + 1, 0, r.url, "tracker timed out"));
|
||||
}
|
||||
if (m_currently_trying_tracker != -1)
|
||||
{
|
||||
TORRENT_ASSERT(m_currently_trying_tracker >= 0);
|
||||
TORRENT_ASSERT(m_currently_trying_tracker < int(m_trackers.size()));
|
||||
TORRENT_ASSERT(m_trackers[m_currently_trying_tracker].url == r.url);
|
||||
|
||||
++m_trackers[m_currently_trying_tracker].fails;
|
||||
}
|
||||
}
|
||||
else if (r.kind == tracker_request::scrape_request)
|
||||
{
|
||||
|
@ -4821,6 +4844,14 @@ namespace libtorrent
|
|||
m_ses.m_alerts.post_alert(tracker_error_alert(get_handle()
|
||||
, m_failed_trackers + 1, response_code, r.url, str));
|
||||
}
|
||||
if (m_currently_trying_tracker != -1)
|
||||
{
|
||||
TORRENT_ASSERT(m_currently_trying_tracker >= 0);
|
||||
TORRENT_ASSERT(m_currently_trying_tracker < int(m_trackers.size()));
|
||||
TORRENT_ASSERT(m_trackers[m_currently_trying_tracker].url == r.url);
|
||||
|
||||
++m_trackers[m_currently_trying_tracker].fails;
|
||||
}
|
||||
}
|
||||
else if (r.kind == tracker_request::scrape_request)
|
||||
{
|
||||
|
|
|
@ -539,6 +539,7 @@ namespace libtorrent
|
|||
announce_entry e(tier->list_string_value_at(k));
|
||||
if (e.url.empty()) continue;
|
||||
e.tier = j;
|
||||
e.fail_limit = 0;
|
||||
m_urls.push_back(e);
|
||||
}
|
||||
}
|
||||
|
@ -563,6 +564,7 @@ namespace libtorrent
|
|||
if (m_urls.empty())
|
||||
{
|
||||
announce_entry e(torrent_file.dict_find_string_value("announce"));
|
||||
e.fail_limit = 0;
|
||||
if (!e.url.empty()) m_urls.push_back(e);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ test-suite libtorrent :
|
|||
[ run test_ip_filter.cpp ]
|
||||
[ run test_hasher.cpp ]
|
||||
[ run test_metadata_extension.cpp ]
|
||||
[ run test_trackers_extension.cpp ]
|
||||
[ run test_swarm.cpp ]
|
||||
[ run test_lsd.cpp ]
|
||||
[ run test_pex.cpp ]
|
||||
|
|
|
@ -50,8 +50,8 @@ void test_transfer(bool clear_files, bool disconnect
|
|||
{
|
||||
using namespace libtorrent;
|
||||
|
||||
session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48100, 49000));
|
||||
session ses2(fingerprint("LT", 0, 1, 0, 0), std::make_pair(49100, 50000));
|
||||
session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48100, 49000), "0.0.0.0", 0);
|
||||
session ses2(fingerprint("LT", 0, 1, 0, 0), std::make_pair(49100, 50000), "0.0.0.0", 0);
|
||||
ses1.add_extension(constructor);
|
||||
ses2.add_extension(constructor);
|
||||
torrent_handle tor1;
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2008, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "libtorrent/session.hpp"
|
||||
#include "libtorrent/hasher.hpp"
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/filesystem/convenience.hpp>
|
||||
|
||||
#include "test.hpp"
|
||||
#include "setup_transfer.hpp"
|
||||
#include "libtorrent/extensions/metadata_transfer.hpp"
|
||||
#include "libtorrent/extensions/ut_metadata.hpp"
|
||||
#include "libtorrent/extensions/lt_trackers.hpp"
|
||||
|
||||
using boost::filesystem::remove_all;
|
||||
using boost::tuples::ignore;
|
||||
|
||||
void test_main()
|
||||
{
|
||||
using namespace libtorrent;
|
||||
|
||||
session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48130, 49000), "0.0.0.0", 0);
|
||||
session ses2(fingerprint("LT", 0, 1, 0, 0), std::make_pair(49130, 50000), "0.0.0.0", 0);
|
||||
ses1.add_extension(create_lt_trackers_plugin);
|
||||
ses2.add_extension(create_lt_trackers_plugin);
|
||||
|
||||
add_torrent_params atp;
|
||||
atp.info_hash = sha1_hash("12345678901234567890");
|
||||
atp.save_path = "./";
|
||||
torrent_handle tor1 = ses1.add_torrent(atp);
|
||||
atp.tracker_url = "http://test.non-existent.com/announce";
|
||||
torrent_handle tor2 = ses2.add_torrent(atp);
|
||||
tor2.connect_peer(tcp::endpoint(address_v4::from_string("127.0.0.1"), ses1.listen_port()));
|
||||
|
||||
for (int i = 0; i < 130; ++i)
|
||||
{
|
||||
// make sure this function can be called on
|
||||
// torrents without metadata
|
||||
print_alerts(ses1, "ses1", false, true);
|
||||
print_alerts(ses2, "ses2", false, true);
|
||||
|
||||
if (tor1.trackers().size() == 1) break;
|
||||
test_sleep(1000);
|
||||
}
|
||||
|
||||
TEST_CHECK(tor1.trackers().size() == 1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue