remove deprecated extensions lt_trackers and metadata_transfer (#941)
This commit is contained in:
parent
4f803353cf
commit
118d06b780
|
@ -116,11 +116,9 @@ set(sources
|
||||||
version
|
version
|
||||||
|
|
||||||
# -- extensions --
|
# -- extensions --
|
||||||
metadata_transfer
|
|
||||||
ut_pex
|
ut_pex
|
||||||
ut_metadata
|
ut_metadata
|
||||||
smart_ban
|
smart_ban
|
||||||
lt_trackers
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# -- kademlia --
|
# -- kademlia --
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
* removed support for lt_trackers and metadata_transfer extensions
|
||||||
|
(pre-dating ut_metadata)
|
||||||
* support windows' CryptoAPI for SHA-1
|
* support windows' CryptoAPI for SHA-1
|
||||||
* separated ssl and crypto options in build
|
* separated ssl and crypto options in build
|
||||||
* remove lazy-bitfield feature
|
* remove lazy-bitfield feature
|
||||||
|
|
2
Jamfile
2
Jamfile
|
@ -675,10 +675,8 @@ SOURCES =
|
||||||
file_progress
|
file_progress
|
||||||
|
|
||||||
# -- extensions --
|
# -- extensions --
|
||||||
metadata_transfer
|
|
||||||
ut_pex
|
ut_pex
|
||||||
ut_metadata
|
ut_metadata
|
||||||
lt_trackers
|
|
||||||
smart_ban
|
smart_ban
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
#include <libtorrent/torrent_info.hpp>
|
#include <libtorrent/torrent_info.hpp>
|
||||||
#include <libtorrent/kademlia/item.hpp> // for sign_mutable_item
|
#include <libtorrent/kademlia/item.hpp> // for sign_mutable_item
|
||||||
#include <libtorrent/alert.hpp>
|
#include <libtorrent/alert.hpp>
|
||||||
#include <libtorrent/extensions/lt_trackers.hpp>
|
|
||||||
#include <libtorrent/extensions/metadata_transfer.hpp>
|
|
||||||
#include <libtorrent/extensions/smart_ban.hpp>
|
#include <libtorrent/extensions/smart_ban.hpp>
|
||||||
#include <libtorrent/extensions/ut_metadata.hpp>
|
#include <libtorrent/extensions/ut_metadata.hpp>
|
||||||
#include <libtorrent/extensions/ut_pex.hpp>
|
#include <libtorrent/extensions/ut_pex.hpp>
|
||||||
|
@ -105,12 +103,6 @@ namespace
|
||||||
s.add_extension(create_ut_pex_plugin);
|
s.add_extension(create_ut_pex_plugin);
|
||||||
else if (name == "smart_ban")
|
else if (name == "smart_ban")
|
||||||
s.add_extension(create_smart_ban_plugin);
|
s.add_extension(create_smart_ban_plugin);
|
||||||
else if (name == "lt_trackers")
|
|
||||||
s.add_extension(create_lt_trackers_plugin);
|
|
||||||
#ifndef TORRENT_NO_DEPRECATE
|
|
||||||
else if (name == "metadata_transfer")
|
|
||||||
s.add_extension(create_metadata_plugin);
|
|
||||||
#endif // TORRENT_NO_DEPRECATE
|
|
||||||
|
|
||||||
#endif // TORRENT_DISABLE_EXTENSIONS
|
#endif // TORRENT_DISABLE_EXTENSIONS
|
||||||
}
|
}
|
||||||
|
@ -884,7 +876,6 @@ void bind_session()
|
||||||
|
|
||||||
def("high_performance_seed", (perf_preset1)high_performance_seed);
|
def("high_performance_seed", (perf_preset1)high_performance_seed);
|
||||||
def("min_memory_usage", (mem_preset1)min_memory_usage);
|
def("min_memory_usage", (mem_preset1)min_memory_usage);
|
||||||
scope().attr("create_metadata_plugin") = "metadata_transfer";
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
def("high_performance_seed", (perf_preset2)high_performance_seed);
|
def("high_performance_seed", (perf_preset2)high_performance_seed);
|
||||||
|
|
|
@ -77,9 +77,7 @@ category_mapping = {
|
||||||
'ut_metadata.hpp': 'Plugins',
|
'ut_metadata.hpp': 'Plugins',
|
||||||
'ut_pex.hpp': 'Plugins',
|
'ut_pex.hpp': 'Plugins',
|
||||||
'ut_trackers.hpp': 'Plugins',
|
'ut_trackers.hpp': 'Plugins',
|
||||||
'metadata_transfer.hpp': 'Plugins',
|
|
||||||
'smart_ban.hpp': 'Plugins',
|
'smart_ban.hpp': 'Plugins',
|
||||||
'lt_trackers.hpp': 'Plugins',
|
|
||||||
'create_torrent.hpp': 'Create Torrents',
|
'create_torrent.hpp': 'Create Torrents',
|
||||||
'alert.hpp': 'Alerts',
|
'alert.hpp': 'Alerts',
|
||||||
'alert_types.hpp': 'Alerts',
|
'alert_types.hpp': 'Alerts',
|
||||||
|
|
|
@ -172,8 +172,6 @@ nobase_include_HEADERS = \
|
||||||
aux_/byteswap.hpp \
|
aux_/byteswap.hpp \
|
||||||
aux_/cppint_import_export.hpp \
|
aux_/cppint_import_export.hpp \
|
||||||
\
|
\
|
||||||
extensions/lt_trackers.hpp \
|
|
||||||
extensions/metadata_transfer.hpp \
|
|
||||||
extensions/smart_ban.hpp \
|
extensions/smart_ban.hpp \
|
||||||
extensions/ut_metadata.hpp \
|
extensions/ut_metadata.hpp \
|
||||||
extensions/ut_pex.hpp \
|
extensions/ut_pex.hpp \
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2008-2016, 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
|
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
|
||||||
|
|
||||||
#include "libtorrent/config.hpp"
|
|
||||||
|
|
||||||
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
|
||||||
|
|
||||||
namespace libtorrent
|
|
||||||
{
|
|
||||||
struct torrent_plugin;
|
|
||||||
struct torrent_handle;
|
|
||||||
|
|
||||||
// constructor function for the trackers exchange extension. This can
|
|
||||||
// either be passed in the add_torrent_params::extensions field, or
|
|
||||||
// via torrent_handle::add_extension().
|
|
||||||
boost::shared_ptr<torrent_plugin> TORRENT_EXPORT create_lt_trackers_plugin(torrent_handle const&, void*);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // TORRENT_DISABLE_EXTENSIONS
|
|
||||||
|
|
||||||
#endif // TORRENT_LT_TRACKERS_HPP_INCLUDED
|
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2006-2016, 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_METADATA_TRANSFER_HPP_INCLUDED
|
|
||||||
#define TORRENT_METADATA_TRANSFER_HPP_INCLUDED
|
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
|
||||||
|
|
||||||
#include "libtorrent/config.hpp"
|
|
||||||
|
|
||||||
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
|
||||||
|
|
||||||
#ifndef TORRENT_NO_DEPRECATE
|
|
||||||
|
|
||||||
namespace libtorrent
|
|
||||||
{
|
|
||||||
struct torrent_plugin;
|
|
||||||
struct torrent_handle;
|
|
||||||
|
|
||||||
#ifndef TORRENT_NO_DEPRECATE
|
|
||||||
// constructor function for the metadata transfer extension. This
|
|
||||||
// extension has been superseded by the ut_metadata extension and
|
|
||||||
// is deprecated. It can be either be passed in the
|
|
||||||
// add_torrent_params::extensions field, or
|
|
||||||
// via torrent_handle::add_extension().
|
|
||||||
TORRENT_DEPRECATED
|
|
||||||
TORRENT_EXPORT boost::shared_ptr<torrent_plugin>
|
|
||||||
create_metadata_plugin(torrent_handle const&, void*);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // TORRENT_DISABLE_EXTENSIONS
|
|
||||||
|
|
||||||
#endif // TORRENT_METADATA_TRANSFER_HPP_INCLUDED
|
|
||||||
|
|
|
@ -449,21 +449,13 @@ namespace libtorrent
|
||||||
// all of these extensions should be added. The main plugins implemented
|
// all of these extensions should be added. The main plugins implemented
|
||||||
// in libtorrent are:
|
// in libtorrent are:
|
||||||
//
|
//
|
||||||
// metadata extension
|
// uTorrent metadata
|
||||||
// Allows peers to download the metadata (.torren files) from the swarm
|
// Allows peers to download the metadata (.torren files) from the swarm
|
||||||
// directly. Makes it possible to join a swarm with just a tracker and
|
// directly. Makes it possible to join a swarm with just a tracker and
|
||||||
// info-hash.
|
// info-hash.
|
||||||
//
|
//
|
||||||
// ::
|
// ::
|
||||||
//
|
//
|
||||||
// #include <libtorrent/extensions/metadata_transfer.hpp>
|
|
||||||
// ses.add_extension(&libtorrent::create_metadata_plugin);
|
|
||||||
//
|
|
||||||
// uTorrent metadata
|
|
||||||
// Same as ``metadata extension`` but compatible with uTorrent.
|
|
||||||
//
|
|
||||||
// ::
|
|
||||||
//
|
|
||||||
// #include <libtorrent/extensions/ut_metadata.hpp>
|
// #include <libtorrent/extensions/ut_metadata.hpp>
|
||||||
// ses.add_extension(&libtorrent::create_ut_metadata_plugin);
|
// ses.add_extension(&libtorrent::create_ut_metadata_plugin);
|
||||||
//
|
//
|
||||||
|
|
|
@ -84,7 +84,7 @@ namespace libtorrent
|
||||||
checking_files,
|
checking_files,
|
||||||
|
|
||||||
// The torrent is trying to download metadata from peers.
|
// The torrent is trying to download metadata from peers.
|
||||||
// This assumes the metadata_transfer extension is in use.
|
// This implies the ut_metadata extension is in use.
|
||||||
downloading_metadata,
|
downloading_metadata,
|
||||||
|
|
||||||
// The torrent is being downloaded. This is the state
|
// The torrent is being downloaded. This is the state
|
||||||
|
|
|
@ -43,7 +43,6 @@ alias libtorrent-sims :
|
||||||
[ run test_dht_storage.cpp ]
|
[ run test_dht_storage.cpp ]
|
||||||
[ run test_pe_crypto.cpp ]
|
[ run test_pe_crypto.cpp ]
|
||||||
[ run test_metadata_extension.cpp ]
|
[ run test_metadata_extension.cpp ]
|
||||||
[ run test_trackers_extension.cpp ]
|
|
||||||
[ run test_tracker.cpp ]
|
[ run test_tracker.cpp ]
|
||||||
[ run test_thread_pool.cpp ]
|
[ run test_thread_pool.cpp ]
|
||||||
[ run test_ip_filter.cpp ]
|
[ run test_ip_filter.cpp ]
|
||||||
|
|
|
@ -40,7 +40,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/torrent_info.hpp"
|
#include "libtorrent/torrent_info.hpp"
|
||||||
#include "libtorrent/add_torrent_params.hpp"
|
#include "libtorrent/add_torrent_params.hpp"
|
||||||
#include "libtorrent/magnet_uri.hpp"
|
#include "libtorrent/magnet_uri.hpp"
|
||||||
#include "libtorrent/extensions/metadata_transfer.hpp"
|
|
||||||
#include "libtorrent/extensions/ut_metadata.hpp"
|
#include "libtorrent/extensions/ut_metadata.hpp"
|
||||||
|
|
||||||
using namespace libtorrent;
|
using namespace libtorrent;
|
||||||
|
|
|
@ -1,156 +0,0 @@
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2008-2015, 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 "setup_swarm.hpp"
|
|
||||||
#include "libtorrent/alert.hpp"
|
|
||||||
#include "libtorrent/announce_entry.hpp"
|
|
||||||
#include "libtorrent/settings_pack.hpp"
|
|
||||||
#include "libtorrent/add_torrent_params.hpp"
|
|
||||||
#include "libtorrent/alert_types.hpp"
|
|
||||||
#include "libtorrent/extensions/lt_trackers.hpp"
|
|
||||||
#include "libtorrent/session.hpp"
|
|
||||||
#include "test.hpp"
|
|
||||||
#include "settings.hpp"
|
|
||||||
|
|
||||||
using namespace libtorrent;
|
|
||||||
|
|
||||||
TORRENT_TEST(plain)
|
|
||||||
{
|
|
||||||
dsl_config network_cfg;
|
|
||||||
sim::simulation sim{network_cfg};
|
|
||||||
|
|
||||||
settings_pack pack = settings();
|
|
||||||
|
|
||||||
add_torrent_params p;
|
|
||||||
p.flags &= ~lt::add_torrent_params::flag_paused;
|
|
||||||
p.flags &= ~lt::add_torrent_params::flag_auto_managed;
|
|
||||||
|
|
||||||
// the default torrent has one tracker
|
|
||||||
// we remove this from session 0 (the one under test)
|
|
||||||
p.trackers.push_back("http://test.non-existent.com/announce");
|
|
||||||
|
|
||||||
bool connected = false;
|
|
||||||
|
|
||||||
setup_swarm(2, swarm_test::upload
|
|
||||||
, sim , pack, p
|
|
||||||
// init session
|
|
||||||
, [](lt::session& ses) {
|
|
||||||
ses.add_extension(&create_lt_trackers_plugin);
|
|
||||||
}
|
|
||||||
// add session
|
|
||||||
, [](lt::settings_pack&) {}
|
|
||||||
// add torrent
|
|
||||||
, [](lt::add_torrent_params& params) {
|
|
||||||
|
|
||||||
// make sure neither peer has any content
|
|
||||||
// TODO: it would be more efficient to not create the content in the first
|
|
||||||
// place
|
|
||||||
params.save_path = save_path(test_counter(), 1);
|
|
||||||
|
|
||||||
// the test is whether this peer will receive the tracker or not
|
|
||||||
params.trackers.clear();
|
|
||||||
}
|
|
||||||
// on alert
|
|
||||||
, [&](lt::alert const* a, lt::session&) {
|
|
||||||
if (alert_cast<lt::peer_connect_alert>(a))
|
|
||||||
connected = true;
|
|
||||||
}
|
|
||||||
// terminate
|
|
||||||
, [&](int ticks, lt::session& ses) -> bool {
|
|
||||||
if (ticks > 10)
|
|
||||||
{
|
|
||||||
TEST_ERROR("timeout");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return connected && ses.get_torrents()[0].trackers().size() > 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
TEST_EQUAL(connected, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
TORRENT_TEST(no_metadata)
|
|
||||||
{
|
|
||||||
dsl_config network_cfg;
|
|
||||||
sim::simulation sim{network_cfg};
|
|
||||||
|
|
||||||
settings_pack pack = settings();
|
|
||||||
|
|
||||||
add_torrent_params p;
|
|
||||||
p.flags &= ~lt::add_torrent_params::flag_paused;
|
|
||||||
p.flags &= ~lt::add_torrent_params::flag_auto_managed;
|
|
||||||
|
|
||||||
// the default torrent has one tracker
|
|
||||||
// we remove this from session 0 (the one under test)
|
|
||||||
p.trackers.push_back("http://test.non-existent.com/announce");
|
|
||||||
|
|
||||||
bool connected = false;
|
|
||||||
|
|
||||||
setup_swarm(2, swarm_test::upload
|
|
||||||
, sim , pack, p
|
|
||||||
// init session
|
|
||||||
, [](lt::session& ses) {
|
|
||||||
ses.add_extension(&create_lt_trackers_plugin);
|
|
||||||
}
|
|
||||||
// add session
|
|
||||||
, [](lt::settings_pack&) {}
|
|
||||||
// add torrent
|
|
||||||
, [](lt::add_torrent_params& params) {
|
|
||||||
|
|
||||||
// make sure neither peer has any content
|
|
||||||
// TODO: it would be more efficient to not create the content in the first
|
|
||||||
// place
|
|
||||||
params.save_path = save_path(test_counter(), 1);
|
|
||||||
|
|
||||||
// the test is whether this peer will receive the tracker or not
|
|
||||||
params.trackers.clear();
|
|
||||||
|
|
||||||
// if we don't have metadata, the other peer should not send the
|
|
||||||
// tracker to us
|
|
||||||
params.info_hash = sha1_hash("aaaaaaaaaaaaaaaaaaaa");
|
|
||||||
params.ti.reset();
|
|
||||||
}
|
|
||||||
// on alert
|
|
||||||
, [&](lt::alert const* a, lt::session&) {
|
|
||||||
if (alert_cast<lt::peer_connect_alert>(a))
|
|
||||||
connected = true;
|
|
||||||
}
|
|
||||||
// terminate
|
|
||||||
, [](int const ticks, lt::session& ses) -> bool {
|
|
||||||
if (ticks < 10)
|
|
||||||
return false;
|
|
||||||
TEST_EQUAL(ses.get_torrents()[0].trackers().size(), 0);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
TEST_EQUAL(connected, true);
|
|
||||||
}
|
|
||||||
|
|
|
@ -83,10 +83,8 @@ libtorrent_rasterbar_la_SOURCES = \
|
||||||
ip_voter.cpp \
|
ip_voter.cpp \
|
||||||
lazy_bdecode.cpp \
|
lazy_bdecode.cpp \
|
||||||
lsd.cpp \
|
lsd.cpp \
|
||||||
lt_trackers.cpp \
|
|
||||||
magnet_uri.cpp \
|
magnet_uri.cpp \
|
||||||
merkle.cpp \
|
merkle.cpp \
|
||||||
metadata_transfer.cpp \
|
|
||||||
natpmp.cpp \
|
natpmp.cpp \
|
||||||
parse_url.cpp \
|
parse_url.cpp \
|
||||||
part_file.cpp \
|
part_file.cpp \
|
||||||
|
|
|
@ -1,395 +0,0 @@
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2008-2016, 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_DISABLE_EXTENSIONS
|
|
||||||
|
|
||||||
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <vector>
|
|
||||||
#include <utility>
|
|
||||||
#include <numeric>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
#include "libtorrent/peer_connection.hpp"
|
|
||||||
#include "libtorrent/bt_peer_connection.hpp"
|
|
||||||
#include "libtorrent/peer_connection_handle.hpp"
|
|
||||||
#include "libtorrent/hasher.hpp"
|
|
||||||
#include "libtorrent/bencode.hpp"
|
|
||||||
#include "libtorrent/torrent.hpp"
|
|
||||||
#include "libtorrent/extensions.hpp"
|
|
||||||
#include "libtorrent/extensions/lt_trackers.hpp"
|
|
||||||
#include "libtorrent/alert_types.hpp"
|
|
||||||
#include "libtorrent/io.hpp"
|
|
||||||
#include "libtorrent/parse_url.hpp"
|
|
||||||
#include "libtorrent/torrent_handle.hpp"
|
|
||||||
#include "libtorrent/announce_entry.hpp"
|
|
||||||
|
|
||||||
using namespace std::placeholders;
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
|
||||||
explicit lt_tracker_plugin(torrent& t)
|
|
||||||
: m_torrent(t)
|
|
||||||
, m_updates(0)
|
|
||||||
, m_2_minutes(110)
|
|
||||||
, m_num_trackers(0)
|
|
||||||
{
|
|
||||||
m_old_trackers = t.trackers();
|
|
||||||
update_list_hash();
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<peer_plugin> new_connection(
|
|
||||||
peer_connection_handle const& pc) override;
|
|
||||||
|
|
||||||
void tick() override
|
|
||||||
{
|
|
||||||
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 (auto const& ent : trackers)
|
|
||||||
{
|
|
||||||
if (std::any_of(m_old_trackers.begin(), m_old_trackers.end()
|
|
||||||
, [&ent](announce_entry const& ae) { return ae.url == ent.url; }))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!send_tracker(ent)) continue;
|
|
||||||
m_old_trackers.push_back(ent);
|
|
||||||
++m_updates;
|
|
||||||
added.push_back(ent.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)
|
|
||||||
, [] (announce_entry const& ae) { return ae.url; });
|
|
||||||
std::sort(canonical_list.begin(), canonical_list.end());
|
|
||||||
|
|
||||||
hasher h;
|
|
||||||
std::for_each(canonical_list.begin(), canonical_list.end()
|
|
||||||
, [&h](std::string const& s) { h.update(s); });
|
|
||||||
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; }
|
|
||||||
|
|
||||||
void increment_tracker_counter() { m_num_trackers++; }
|
|
||||||
int num_tex_trackers() const { return m_num_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;
|
|
||||||
int m_num_trackers;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
void add_handshake(entry& h) override
|
|
||||||
{
|
|
||||||
entry& messages = h["m"];
|
|
||||||
messages["lt_tex"] = 19;
|
|
||||||
h["tr"] = m_tp.list_hash().to_string();
|
|
||||||
}
|
|
||||||
|
|
||||||
// called when the extension handshake from the other end is received
|
|
||||||
bool on_extension_handshake(bdecode_node const& h) override
|
|
||||||
{
|
|
||||||
m_message_index = 0;
|
|
||||||
if (h.type() != bdecode_node::dict_t) return false;
|
|
||||||
bdecode_node messages = h.dict_find("m");
|
|
||||||
if (!messages || messages.type() != bdecode_node::dict_t) return false;
|
|
||||||
|
|
||||||
int index = int(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool on_extended(int /* length */
|
|
||||||
, int extended_msg, buffer::const_interval body) override
|
|
||||||
{
|
|
||||||
if (extended_msg != 19) return false;
|
|
||||||
if (m_message_index == 0) return false;
|
|
||||||
if (!m_pc.packet_finished()) return true;
|
|
||||||
|
|
||||||
bdecode_node msg;
|
|
||||||
error_code ec;
|
|
||||||
int ret = bdecode(body.begin, body.end, msg, ec);
|
|
||||||
if (ret != 0 || msg.type() != bdecode_node::dict_t)
|
|
||||||
{
|
|
||||||
m_pc.disconnect(errors::invalid_lt_tracker_message, op_bittorrent, 2);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bdecode_node added = msg.dict_find_list("added");
|
|
||||||
|
|
||||||
// invalid tex message
|
|
||||||
if (added == 0)
|
|
||||||
{
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
|
||||||
m_pc.peer_log(peer_log_alert::incoming_message, "LT_TEX"
|
|
||||||
, "NOT A DICTIONARY");
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_tp.num_tex_trackers() >= 50)
|
|
||||||
{
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
|
||||||
m_pc.peer_log(peer_log_alert::incoming_message, "LT_TEX"
|
|
||||||
, "we already have %d trackers from tex, don't add any more"
|
|
||||||
, m_tp.num_tex_trackers());
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
|
||||||
m_pc.peer_log(peer_log_alert::incoming_message, "LT_TEX");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (int i = 0; i < added.list_size(); ++i)
|
|
||||||
{
|
|
||||||
announce_entry e(added.list_string_value_at(i));
|
|
||||||
if (e.url.empty()) continue;
|
|
||||||
|
|
||||||
// ignore urls with binary data in them
|
|
||||||
if (need_encoding(e.url.c_str(), int(e.url.size()))) continue;
|
|
||||||
|
|
||||||
// ignore invalid URLs
|
|
||||||
error_code err;
|
|
||||||
std::string protocol;
|
|
||||||
std::string auth;
|
|
||||||
std::string hostname;
|
|
||||||
int port;
|
|
||||||
std::string path;
|
|
||||||
std::tie(protocol, auth, hostname, port, path)
|
|
||||||
= parse_url_components(e.url, err);
|
|
||||||
if (err) continue;
|
|
||||||
|
|
||||||
// ignore unknown protocols
|
|
||||||
if (protocol != "udp" && protocol != "http" && protocol != "https")
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// ignore invalid ports
|
|
||||||
if (port == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (m_tp.num_tex_trackers() >= 50)
|
|
||||||
break;
|
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
|
||||||
m_pc.peer_log(peer_log_alert::info, "LT_TEX", "adding: %s", e.url.c_str());
|
|
||||||
#endif
|
|
||||||
e.fail_limit = 1;
|
|
||||||
e.send_stats = false;
|
|
||||||
e.source = announce_entry::source_tex;
|
|
||||||
if (m_torrent.add_tracker(e))
|
|
||||||
m_tp.increment_tracker_counter();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tick() override
|
|
||||||
{
|
|
||||||
// no handshake yet
|
|
||||||
if (!m_message_index) return;
|
|
||||||
if (++m_2_minutes <= 120) return;
|
|
||||||
m_2_minutes = 0;
|
|
||||||
|
|
||||||
if (m_full_list)
|
|
||||||
{
|
|
||||||
if (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;
|
|
||||||
|
|
||||||
if (!m_torrent.valid_metadata() || m_torrent.torrent_file().priv())
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::vector<char> const& tex_msg = m_tp.get_lt_tex_msg();
|
|
||||||
|
|
||||||
char msg[6];
|
|
||||||
char* ptr = msg;
|
|
||||||
|
|
||||||
detail::write_uint32(1 + 1 + int(tex_msg.size()), ptr);
|
|
||||||
detail::write_uint8(bt_peer_connection::msg_extended, ptr);
|
|
||||||
detail::write_uint8(m_message_index, ptr);
|
|
||||||
m_pc.send_buffer(msg, sizeof(msg));
|
|
||||||
m_pc.send_buffer(&tex_msg[0], int(tex_msg.size()));
|
|
||||||
m_pc.setup_send();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool send_full_tex_list() const
|
|
||||||
{
|
|
||||||
if (m_tp.trackers().empty()) return false;
|
|
||||||
|
|
||||||
if (!m_torrent.valid_metadata() || m_torrent.torrent_file().priv())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
|
||||||
m_pc.peer_log(peer_log_alert::outgoing_message, "LT_TEX");
|
|
||||||
#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);
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
|
||||||
m_pc.peer_log(peer_log_alert::info, "LT_TEX"
|
|
||||||
, "sending: %s", i->url.c_str());
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
std::vector<char> tex_msg;
|
|
||||||
bencode(std::back_inserter(tex_msg), tex);
|
|
||||||
|
|
||||||
char msg[6];
|
|
||||||
char* ptr = msg;
|
|
||||||
|
|
||||||
detail::write_uint32(1 + 1 + int(tex_msg.size()), ptr);
|
|
||||||
detail::write_uint8(bt_peer_connection::msg_extended, ptr);
|
|
||||||
detail::write_uint8(m_message_index, ptr);
|
|
||||||
m_pc.send_buffer(msg, sizeof(msg));
|
|
||||||
m_pc.send_buffer(&tex_msg[0], int(tex_msg.size()));
|
|
||||||
m_pc.setup_send();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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_handle const& pc)
|
|
||||||
{
|
|
||||||
if (pc.type() != peer_connection::bittorrent_connection)
|
|
||||||
return boost::shared_ptr<peer_plugin>();
|
|
||||||
|
|
||||||
if (m_torrent.valid_metadata() && m_torrent.torrent_file().priv())
|
|
||||||
return boost::shared_ptr<peer_plugin>();
|
|
||||||
|
|
||||||
bt_peer_connection* c = static_cast<bt_peer_connection*>(pc.native_handle().get());
|
|
||||||
return boost::shared_ptr<peer_plugin>(new lt_tracker_peer_plugin(m_torrent, *c, *this));
|
|
||||||
}
|
|
||||||
|
|
||||||
} }
|
|
||||||
|
|
||||||
namespace libtorrent
|
|
||||||
{
|
|
||||||
|
|
||||||
boost::shared_ptr<torrent_plugin> TORRENT_EXPORT create_lt_trackers_plugin(torrent_handle const& th, void*)
|
|
||||||
{
|
|
||||||
torrent* t = th.native_handle().get();
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,616 +0,0 @@
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2006-2016, 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_NO_DEPRECATE
|
|
||||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
|
||||||
|
|
||||||
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <utility>
|
|
||||||
#include <numeric>
|
|
||||||
#include <algorithm> // count
|
|
||||||
|
|
||||||
#include "libtorrent/peer_connection.hpp"
|
|
||||||
#include "libtorrent/bt_peer_connection.hpp"
|
|
||||||
#include "libtorrent/peer_connection_handle.hpp"
|
|
||||||
#include "libtorrent/hasher.hpp"
|
|
||||||
#include "libtorrent/bencode.hpp"
|
|
||||||
#include "libtorrent/torrent.hpp"
|
|
||||||
#include "libtorrent/torrent_handle.hpp"
|
|
||||||
#include "libtorrent/extensions.hpp"
|
|
||||||
#include "libtorrent/extensions/metadata_transfer.hpp"
|
|
||||||
#include "libtorrent/alert_types.hpp"
|
|
||||||
#include "libtorrent/buffer.hpp"
|
|
||||||
#include "libtorrent/io.hpp"
|
|
||||||
|
|
||||||
namespace libtorrent { namespace
|
|
||||||
{
|
|
||||||
int div_round_up(int numerator, int denominator)
|
|
||||||
{
|
|
||||||
return (numerator + denominator - 1) / denominator;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<int, int> req_to_offset(std::pair<int, int> req, int total_size)
|
|
||||||
{
|
|
||||||
TORRENT_ASSERT(req.first >= 0);
|
|
||||||
TORRENT_ASSERT(req.second > 0);
|
|
||||||
TORRENT_ASSERT(req.second <= 256);
|
|
||||||
TORRENT_ASSERT(req.first + req.second <= 256);
|
|
||||||
|
|
||||||
int start = div_round_up(req.first * total_size, 256);
|
|
||||||
int size = div_round_up((req.first + req.second) * total_size, 256) - start;
|
|
||||||
return std::make_pair(start, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<int, int> offset_to_req(std::pair<int, int> offset, int total_size)
|
|
||||||
{
|
|
||||||
int start = offset.first * 256 / total_size;
|
|
||||||
int size = (offset.first + offset.second) * 256 / total_size - start;
|
|
||||||
|
|
||||||
std::pair<int, int> ret(start, size);
|
|
||||||
|
|
||||||
TORRENT_ASSERT(start >= 0);
|
|
||||||
TORRENT_ASSERT(size > 0);
|
|
||||||
TORRENT_ASSERT(start <= 256);
|
|
||||||
TORRENT_ASSERT(start + size <= 256);
|
|
||||||
|
|
||||||
// assert the identity of this function
|
|
||||||
#if TORRENT_USE_ASSERTS
|
|
||||||
std::pair<int, int> identity = req_to_offset(ret, total_size);
|
|
||||||
TORRENT_ASSERT(offset == identity);
|
|
||||||
#endif
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct metadata_plugin final
|
|
||||||
: torrent_plugin
|
|
||||||
{
|
|
||||||
explicit metadata_plugin(torrent& t)
|
|
||||||
: m_torrent(t)
|
|
||||||
, m_metadata_progress(0)
|
|
||||||
, m_metadata_size(0)
|
|
||||||
{
|
|
||||||
m_requested_metadata.resize(256, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
bool need_loaded()
|
|
||||||
{ return m_torrent.need_loaded(); }
|
|
||||||
*/
|
|
||||||
void on_unload() override
|
|
||||||
{
|
|
||||||
m_metadata.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_load() override
|
|
||||||
{
|
|
||||||
// initialize m_metadata_size
|
|
||||||
TORRENT_ASSERT(m_torrent.is_loaded());
|
|
||||||
metadata();
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_files_checked() override
|
|
||||||
{
|
|
||||||
// if the torrent is a seed, make a reference to
|
|
||||||
// the metadata from the torrent before it is deallocated
|
|
||||||
if (m_torrent.is_seed()) metadata();
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<peer_plugin> new_connection(
|
|
||||||
peer_connection_handle const& pc) override;
|
|
||||||
|
|
||||||
buffer::const_interval metadata() const
|
|
||||||
{
|
|
||||||
if (!m_metadata)
|
|
||||||
{
|
|
||||||
m_metadata = m_torrent.torrent_file().metadata();
|
|
||||||
m_metadata_size = m_torrent.torrent_file().metadata_size();
|
|
||||||
TORRENT_ASSERT(hasher(m_metadata.get(), m_metadata_size).final()
|
|
||||||
== m_torrent.torrent_file().info_hash());
|
|
||||||
}
|
|
||||||
return buffer::const_interval(m_metadata.get(), m_metadata.get()
|
|
||||||
+ m_metadata_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool received_metadata(char const* buf, int size, int offset, int total_size)
|
|
||||||
{
|
|
||||||
if (m_torrent.valid_metadata()) return false;
|
|
||||||
|
|
||||||
if (!m_metadata || m_metadata_size < total_size)
|
|
||||||
{
|
|
||||||
m_metadata.reset(new char[total_size]);
|
|
||||||
m_metadata_size = total_size;
|
|
||||||
}
|
|
||||||
std::copy(buf, buf + size, &m_metadata[offset]);
|
|
||||||
|
|
||||||
if (m_have_metadata.empty())
|
|
||||||
m_have_metadata.resize(256, false);
|
|
||||||
|
|
||||||
std::pair<int, int> req = offset_to_req(std::make_pair(offset, size)
|
|
||||||
, total_size);
|
|
||||||
|
|
||||||
TORRENT_ASSERT(req.first + req.second <= int(m_have_metadata.size()));
|
|
||||||
|
|
||||||
std::fill(
|
|
||||||
m_have_metadata.begin() + req.first
|
|
||||||
, m_have_metadata.begin() + req.first + req.second
|
|
||||||
, true);
|
|
||||||
|
|
||||||
bool have_all = std::count(
|
|
||||||
m_have_metadata.begin()
|
|
||||||
, m_have_metadata.end()
|
|
||||||
, true) == 256;
|
|
||||||
|
|
||||||
if (!have_all) return false;
|
|
||||||
|
|
||||||
if (!m_torrent.set_metadata(&m_metadata[0], m_metadata_size))
|
|
||||||
{
|
|
||||||
std::fill(
|
|
||||||
m_have_metadata.begin()
|
|
||||||
, m_have_metadata.begin() + req.first + req.second
|
|
||||||
, false);
|
|
||||||
m_metadata_progress = 0;
|
|
||||||
m_metadata_size = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear the storage for the bitfield
|
|
||||||
std::vector<bool>().swap(m_have_metadata);
|
|
||||||
std::vector<int>().swap(m_requested_metadata);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns a range of the metadata that
|
|
||||||
// we should request.
|
|
||||||
std::pair<int, int> metadata_request();
|
|
||||||
|
|
||||||
void cancel_metadata_request(std::pair<int, int> req)
|
|
||||||
{
|
|
||||||
for (int i = req.first; i < req.first + req.second; ++i)
|
|
||||||
{
|
|
||||||
TORRENT_ASSERT(m_requested_metadata[i] > 0);
|
|
||||||
if (m_requested_metadata[i] > 0)
|
|
||||||
--m_requested_metadata[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is called from the peer_connection for
|
|
||||||
// each piece of metadata it receives
|
|
||||||
void metadata_progress(int total_size, int received)
|
|
||||||
{
|
|
||||||
m_metadata_progress += received;
|
|
||||||
m_metadata_size = total_size;
|
|
||||||
m_torrent.set_progress_ppm(std::int64_t(m_metadata_progress) * 1000000 / m_metadata_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_piece_pass(int) override
|
|
||||||
{
|
|
||||||
// if we became a seed, copy the metadata from
|
|
||||||
// the torrent before it is deallocated
|
|
||||||
if (m_torrent.is_seed())
|
|
||||||
metadata();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
int metadata_size() const { return m_metadata_size; }
|
|
||||||
*/
|
|
||||||
|
|
||||||
private:
|
|
||||||
torrent& m_torrent;
|
|
||||||
|
|
||||||
// this buffer is filled with the info-section of
|
|
||||||
// the metadata file while downloading it from
|
|
||||||
// peers, and while sending it.
|
|
||||||
// it is mutable because it's generated lazily
|
|
||||||
mutable boost::shared_array<char> m_metadata;
|
|
||||||
|
|
||||||
int m_metadata_progress;
|
|
||||||
mutable int m_metadata_size;
|
|
||||||
|
|
||||||
// this is a bitfield of size 256, each bit represents
|
|
||||||
// a piece of the metadata. It is set to one if we
|
|
||||||
// have that piece. This vector may be empty
|
|
||||||
// (size 0) if we haven't received any metadata
|
|
||||||
// or if we already have all metadata
|
|
||||||
std::vector<bool> m_have_metadata;
|
|
||||||
// this vector keeps track of how many times each meatdata
|
|
||||||
// block has been requested
|
|
||||||
std::vector<int> m_requested_metadata;
|
|
||||||
|
|
||||||
// explicitly disallow assignment, to silence msvc warning
|
|
||||||
metadata_plugin& operator=(metadata_plugin const&);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct metadata_peer_plugin final
|
|
||||||
: peer_plugin
|
|
||||||
{
|
|
||||||
metadata_peer_plugin(torrent& t, peer_connection& pc
|
|
||||||
, metadata_plugin& tp)
|
|
||||||
: m_waiting_metadata_request(false)
|
|
||||||
, m_message_index(0)
|
|
||||||
, m_metadata_progress(0)
|
|
||||||
, m_no_metadata(min_time())
|
|
||||||
, m_metadata_request(min_time())
|
|
||||||
, m_torrent(t)
|
|
||||||
, m_pc(pc)
|
|
||||||
, m_tp(tp)
|
|
||||||
{}
|
|
||||||
|
|
||||||
char const* type() const override { return "LT_metadata"; }
|
|
||||||
|
|
||||||
// can add entries to the extension handshake
|
|
||||||
void add_handshake(entry& h) override
|
|
||||||
{
|
|
||||||
entry& messages = h["m"];
|
|
||||||
messages["LT_metadata"] = 14;
|
|
||||||
}
|
|
||||||
|
|
||||||
// called when the extension handshake from the other end is received
|
|
||||||
bool on_extension_handshake(bdecode_node const& h) override
|
|
||||||
{
|
|
||||||
m_message_index = 0;
|
|
||||||
if (h.type() != bdecode_node::dict_t) return false;
|
|
||||||
bdecode_node messages = h.dict_find("m");
|
|
||||||
if (!messages || messages.type() != bdecode_node::dict_t) return false;
|
|
||||||
|
|
||||||
int index = int(messages.dict_find_int_value("LT_metadata", -1));
|
|
||||||
if (index == -1) return false;
|
|
||||||
m_message_index = index;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_metadata_request(std::pair<int, int> req)
|
|
||||||
{
|
|
||||||
TORRENT_ASSERT(req.first >= 0);
|
|
||||||
TORRENT_ASSERT(req.second > 0);
|
|
||||||
TORRENT_ASSERT(req.first + req.second <= 256);
|
|
||||||
TORRENT_ASSERT(!m_pc.associated_torrent().expired());
|
|
||||||
TORRENT_ASSERT(!m_pc.associated_torrent().lock()->valid_metadata());
|
|
||||||
|
|
||||||
int start = req.first;
|
|
||||||
int size = req.second;
|
|
||||||
|
|
||||||
// abort if the peer doesn't support the metadata extension
|
|
||||||
if (m_message_index == 0) return;
|
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
|
||||||
m_pc.peer_log(peer_log_alert::outgoing_message, "METADATA_REQUEST"
|
|
||||||
, "start: %d size: %d", start, size);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char msg[9];
|
|
||||||
char* ptr = msg;
|
|
||||||
|
|
||||||
detail::write_uint32(1 + 1 + 3, ptr);
|
|
||||||
detail::write_uint8(bt_peer_connection::msg_extended, ptr);
|
|
||||||
detail::write_uint8(m_message_index, ptr);
|
|
||||||
// means 'request data'
|
|
||||||
detail::write_uint8(0, ptr);
|
|
||||||
detail::write_uint8(start, ptr);
|
|
||||||
detail::write_uint8(size - 1, ptr);
|
|
||||||
m_pc.send_buffer(msg, sizeof(msg));
|
|
||||||
m_pc.setup_send();
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_metadata(std::pair<int, int> req)
|
|
||||||
{
|
|
||||||
TORRENT_ASSERT(req.first >= 0);
|
|
||||||
TORRENT_ASSERT(req.second > 0);
|
|
||||||
TORRENT_ASSERT(req.second <= 256);
|
|
||||||
TORRENT_ASSERT(req.first + req.second <= 256);
|
|
||||||
TORRENT_ASSERT(!m_pc.associated_torrent().expired());
|
|
||||||
|
|
||||||
// abort if the peer doesn't support the metadata extension
|
|
||||||
if (m_message_index == 0) return;
|
|
||||||
|
|
||||||
if (m_torrent.valid_metadata())
|
|
||||||
{
|
|
||||||
std::pair<int, int> offset
|
|
||||||
= req_to_offset(req, int(m_tp.metadata().left()));
|
|
||||||
|
|
||||||
char msg[15];
|
|
||||||
char* ptr = msg;
|
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
|
||||||
m_pc.peer_log(peer_log_alert::outgoing_message, "METADATA"
|
|
||||||
, "start: %d total_size: %d offset: %d data_size: %d"
|
|
||||||
, req.first, req.second, offset.first, offset.second);
|
|
||||||
#endif
|
|
||||||
// yes, we have metadata, send it
|
|
||||||
detail::write_uint32(11 + offset.second, ptr);
|
|
||||||
detail::write_uint8(bt_peer_connection::msg_extended, ptr);
|
|
||||||
detail::write_uint8(m_message_index, ptr);
|
|
||||||
// means 'data packet'
|
|
||||||
detail::write_uint8(1, ptr);
|
|
||||||
detail::write_uint32(int(m_tp.metadata().left()), ptr);
|
|
||||||
detail::write_uint32(offset.first, ptr);
|
|
||||||
m_pc.send_buffer(msg, sizeof(msg));
|
|
||||||
|
|
||||||
// TODO: this is not safe. The torrent could be unloaded while
|
|
||||||
// we're still sending the metadata
|
|
||||||
char const* metadata = m_tp.metadata().begin;
|
|
||||||
m_pc.append_const_send_buffer(metadata + offset.first, offset.second);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
|
||||||
m_pc.peer_log(peer_log_alert::outgoing_message, "METADATA"
|
|
||||||
, "don't have metadata");
|
|
||||||
#endif
|
|
||||||
char msg[4+3];
|
|
||||||
char* ptr = msg;
|
|
||||||
|
|
||||||
// we don't have the metadata, reply with
|
|
||||||
// don't have-message
|
|
||||||
detail::write_uint32(1 + 2, ptr);
|
|
||||||
detail::write_uint8(bt_peer_connection::msg_extended, ptr);
|
|
||||||
detail::write_uint8(m_message_index, ptr);
|
|
||||||
// means 'have no data'
|
|
||||||
detail::write_uint8(2, ptr);
|
|
||||||
m_pc.send_buffer(msg, sizeof(msg));
|
|
||||||
}
|
|
||||||
m_pc.setup_send();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool on_extended(int length
|
|
||||||
, int msg, buffer::const_interval body) override
|
|
||||||
{
|
|
||||||
if (msg != 14) return false;
|
|
||||||
if (m_message_index == 0) return false;
|
|
||||||
|
|
||||||
if (length > 500 * 1024)
|
|
||||||
{
|
|
||||||
m_pc.disconnect(errors::metadata_too_large, op_bittorrent, 2);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (body.left() < 1) return true;
|
|
||||||
int type = detail::read_uint8(body.begin);
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case 0: // request
|
|
||||||
{
|
|
||||||
if (body.left() < 2) return true;
|
|
||||||
int start = detail::read_uint8(body.begin);
|
|
||||||
int size = detail::read_uint8(body.begin) + 1;
|
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
|
||||||
m_pc.peer_log(peer_log_alert::incoming_message, "METADATA_REQUEST"
|
|
||||||
, "start: %d size: %d", start, size);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (length != 3)
|
|
||||||
{
|
|
||||||
// invalid metadata request
|
|
||||||
m_pc.disconnect(errors::invalid_metadata_request, op_bittorrent, 2);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
write_metadata(std::make_pair(start, size));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 1: // data
|
|
||||||
{
|
|
||||||
if (body.left() < 8) return true;
|
|
||||||
|
|
||||||
int total_size = detail::read_int32(body.begin);
|
|
||||||
int offset = detail::read_int32(body.begin);
|
|
||||||
int data_size = length - 9;
|
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
|
||||||
m_pc.peer_log(peer_log_alert::incoming_message, "METADATA"
|
|
||||||
, "total_size: %d | offset: %d | data_size: %d"
|
|
||||||
,total_size, offset, data_size);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (total_size > m_torrent.session().settings().get_int(settings_pack::max_metadata_size))
|
|
||||||
{
|
|
||||||
m_pc.disconnect(errors::metadata_too_large, op_bittorrent, 2);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (total_size <= 0)
|
|
||||||
{
|
|
||||||
m_pc.disconnect(errors::invalid_metadata_size, op_bittorrent, 2);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (offset > total_size || offset < 0)
|
|
||||||
{
|
|
||||||
m_pc.disconnect(errors::invalid_metadata_offset, op_bittorrent, 2);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (offset + data_size > total_size)
|
|
||||||
{
|
|
||||||
m_pc.disconnect(errors::invalid_metadata_message, op_bittorrent, 2);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_tp.metadata_progress(total_size
|
|
||||||
, body.left() - m_metadata_progress);
|
|
||||||
m_metadata_progress = body.left();
|
|
||||||
|
|
||||||
if (body.left() < data_size) return true;
|
|
||||||
|
|
||||||
m_waiting_metadata_request = false;
|
|
||||||
m_tp.received_metadata(body.begin, data_size
|
|
||||||
, offset, total_size);
|
|
||||||
m_metadata_progress = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2: // have no data
|
|
||||||
m_no_metadata = aux::time_now();
|
|
||||||
if (m_waiting_metadata_request)
|
|
||||||
m_tp.cancel_metadata_request(m_last_metadata_request);
|
|
||||||
m_waiting_metadata_request = false;
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
|
||||||
m_pc.peer_log(peer_log_alert::incoming_message, "METADATA"
|
|
||||||
, "don't have metadata");
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
m_pc.disconnect(errors::invalid_metadata_message, op_bittorrent, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tick() override
|
|
||||||
{
|
|
||||||
if (m_pc.is_disconnecting()) return;
|
|
||||||
|
|
||||||
// if we don't have any metadata, and this peer
|
|
||||||
// supports the request metadata extension
|
|
||||||
// and we aren't currently waiting for a request
|
|
||||||
// reply. Then, send a request for some metadata.
|
|
||||||
if (!m_torrent.valid_metadata()
|
|
||||||
&& m_message_index != 0
|
|
||||||
&& !m_waiting_metadata_request
|
|
||||||
&& has_metadata())
|
|
||||||
{
|
|
||||||
m_last_metadata_request = m_tp.metadata_request();
|
|
||||||
write_metadata_request(m_last_metadata_request);
|
|
||||||
m_waiting_metadata_request = true;
|
|
||||||
m_metadata_request = aux::time_now();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool has_metadata() const
|
|
||||||
{
|
|
||||||
return aux::time_now() - minutes(5) > m_no_metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// this is set to true when we send a metadata
|
|
||||||
// request to this peer, and reset to false when
|
|
||||||
// we receive a reply to our request.
|
|
||||||
bool m_waiting_metadata_request;
|
|
||||||
|
|
||||||
// this is the message index the remote peer uses
|
|
||||||
// for metadata extension messages.
|
|
||||||
int m_message_index;
|
|
||||||
|
|
||||||
// the number of bytes of metadata we have received
|
|
||||||
// so far from this per, only counting the current
|
|
||||||
// request. Any previously finished requests
|
|
||||||
// that have been forwarded to the torrent object
|
|
||||||
// do not count.
|
|
||||||
int m_metadata_progress;
|
|
||||||
|
|
||||||
// this is set to the current time each time we get a
|
|
||||||
// "I don't have metadata" message.
|
|
||||||
time_point m_no_metadata;
|
|
||||||
|
|
||||||
// this is set to the time when we last sent
|
|
||||||
// a request for metadata to this peer
|
|
||||||
time_point m_metadata_request;
|
|
||||||
|
|
||||||
// if we're waiting for a metadata request
|
|
||||||
// this was the request we sent
|
|
||||||
std::pair<int, int> m_last_metadata_request;
|
|
||||||
|
|
||||||
torrent& m_torrent;
|
|
||||||
peer_connection& m_pc;
|
|
||||||
metadata_plugin& m_tp;
|
|
||||||
|
|
||||||
// explicitly disallow assignment, to silence msvc warning
|
|
||||||
metadata_peer_plugin& operator=(metadata_peer_plugin const&);
|
|
||||||
};
|
|
||||||
|
|
||||||
boost::shared_ptr<peer_plugin> metadata_plugin::new_connection(
|
|
||||||
peer_connection_handle const& pc)
|
|
||||||
{
|
|
||||||
if (pc.type() != peer_connection::bittorrent_connection)
|
|
||||||
return boost::shared_ptr<peer_plugin>();
|
|
||||||
|
|
||||||
return boost::shared_ptr<peer_plugin>(new metadata_peer_plugin(m_torrent, *pc.native_handle(), *this));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<int, int> metadata_plugin::metadata_request()
|
|
||||||
{
|
|
||||||
// the number of blocks to request
|
|
||||||
int num_blocks = 256 / 4;
|
|
||||||
TORRENT_ASSERT(num_blocks <= 128);
|
|
||||||
|
|
||||||
int min_element = (std::numeric_limits<int>::max)();
|
|
||||||
int best_index = 0;
|
|
||||||
for (int i = 0; i < 256 - num_blocks + 1; ++i)
|
|
||||||
{
|
|
||||||
int min = *std::min_element(m_requested_metadata.begin() + i
|
|
||||||
, m_requested_metadata.begin() + i + num_blocks);
|
|
||||||
min += std::accumulate(m_requested_metadata.begin() + i
|
|
||||||
, m_requested_metadata.begin() + i + num_blocks, int(0));
|
|
||||||
|
|
||||||
if (min_element > min)
|
|
||||||
{
|
|
||||||
best_index = i;
|
|
||||||
min_element = min;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<int, int> ret(best_index, num_blocks);
|
|
||||||
for (int i = ret.first; i < ret.first + ret.second; ++i)
|
|
||||||
m_requested_metadata[i]++;
|
|
||||||
|
|
||||||
TORRENT_ASSERT(ret.first >= 0);
|
|
||||||
TORRENT_ASSERT(ret.second > 0);
|
|
||||||
TORRENT_ASSERT(ret.second <= 256);
|
|
||||||
TORRENT_ASSERT(ret.first + ret.second <= 256);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
} }
|
|
||||||
|
|
||||||
namespace libtorrent
|
|
||||||
{
|
|
||||||
|
|
||||||
boost::shared_ptr<torrent_plugin> create_metadata_plugin(torrent_handle const& th, void*)
|
|
||||||
{
|
|
||||||
torrent* t = th.native_handle().get();
|
|
||||||
// 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
Loading…
Reference in New Issue