forked from premiere/premiere-libtorrent
simplify session pause mechanism by keeping two separate states in torrents and having the session explicitly tell torrents when it's pausing (#779)
This commit is contained in:
parent
42a9022065
commit
be67553897
|
@ -369,7 +369,7 @@ namespace libtorrent
|
||||||
, int protocol, error_code const& ec, int nat_transport);
|
, int protocol, error_code const& ec, int nat_transport);
|
||||||
|
|
||||||
bool is_aborted() const override { return m_abort; }
|
bool is_aborted() const override { return m_abort; }
|
||||||
bool is_paused() const override { return m_paused; }
|
bool is_paused() const { return m_paused; }
|
||||||
|
|
||||||
void pause();
|
void pause();
|
||||||
void resume();
|
void resume();
|
||||||
|
|
|
@ -176,7 +176,6 @@ namespace libtorrent { namespace aux
|
||||||
|
|
||||||
virtual boost::uint16_t session_time() const = 0;
|
virtual boost::uint16_t session_time() const = 0;
|
||||||
|
|
||||||
virtual bool is_paused() const = 0;
|
|
||||||
virtual bool is_aborted() const = 0;
|
virtual bool is_aborted() const = 0;
|
||||||
virtual int num_uploads() const = 0;
|
virtual int num_uploads() const = 0;
|
||||||
virtual bool preemptive_unchoke() const = 0;
|
virtual bool preemptive_unchoke() const = 0;
|
||||||
|
|
|
@ -173,7 +173,7 @@ namespace libtorrent
|
||||||
struct TORRENT_EXTRA_EXPORT torrent_hot_members
|
struct TORRENT_EXTRA_EXPORT torrent_hot_members
|
||||||
{
|
{
|
||||||
torrent_hot_members(aux::session_interface& ses
|
torrent_hot_members(aux::session_interface& ses
|
||||||
, add_torrent_params const& p, int block_size);
|
, add_torrent_params const& p, int block_size, bool session_paused);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// the piece picker. This is allocated lazily. When we don't
|
// the piece picker. This is allocated lazily. When we don't
|
||||||
|
@ -225,6 +225,10 @@ namespace libtorrent
|
||||||
// is true if this torrent has allows having peers
|
// is true if this torrent has allows having peers
|
||||||
bool m_paused:1;
|
bool m_paused:1;
|
||||||
|
|
||||||
|
// is true if the session is paused, in which case the torrent is
|
||||||
|
// effectively paused as well.
|
||||||
|
bool m_session_paused:1;
|
||||||
|
|
||||||
// this is set when the torrent is in share-mode
|
// this is set when the torrent is in share-mode
|
||||||
bool m_share_mode:1;
|
bool m_share_mode:1;
|
||||||
|
|
||||||
|
@ -274,7 +278,7 @@ namespace libtorrent
|
||||||
public:
|
public:
|
||||||
|
|
||||||
torrent(aux::session_interface& ses, int block_size
|
torrent(aux::session_interface& ses, int block_size
|
||||||
, int seq, add_torrent_params const& p
|
, int seq, bool session_paused, add_torrent_params const& p
|
||||||
, sha1_hash const& info_hash);
|
, sha1_hash const& info_hash);
|
||||||
~torrent();
|
~torrent();
|
||||||
|
|
||||||
|
@ -458,6 +462,7 @@ namespace libtorrent
|
||||||
flag_graceful_pause = 1,
|
flag_graceful_pause = 1,
|
||||||
flag_clear_disk_cache = 2
|
flag_clear_disk_cache = 2
|
||||||
};
|
};
|
||||||
|
void set_session_paused(bool b);
|
||||||
void set_paused(bool b, int flags = flag_clear_disk_cache);
|
void set_paused(bool b, int flags = flag_clear_disk_cache);
|
||||||
void set_announce_to_dht(bool b) { m_announce_to_dht = b; }
|
void set_announce_to_dht(bool b) { m_announce_to_dht = b; }
|
||||||
void set_announce_to_trackers(bool b) { m_announce_to_trackers = b; }
|
void set_announce_to_trackers(bool b) { m_announce_to_trackers = b; }
|
||||||
|
|
|
@ -24,6 +24,7 @@ project
|
||||||
;
|
;
|
||||||
|
|
||||||
alias libtorrent-sims :
|
alias libtorrent-sims :
|
||||||
|
[ run test_pause.cpp ]
|
||||||
[ run test_socks5.cpp ]
|
[ run test_socks5.cpp ]
|
||||||
[ run test_checking.cpp ]
|
[ run test_checking.cpp ]
|
||||||
[ run test_optimistic_unchoke.cpp ]
|
[ run test_optimistic_unchoke.cpp ]
|
||||||
|
|
|
@ -53,9 +53,11 @@ struct fake_peer
|
||||||
fake_peer(simulation& sim, char const* ip)
|
fake_peer(simulation& sim, char const* ip)
|
||||||
: m_ios(sim, asio::ip::address::from_string(ip))
|
: m_ios(sim, asio::ip::address::from_string(ip))
|
||||||
, m_acceptor(m_ios)
|
, m_acceptor(m_ios)
|
||||||
, m_in_socket(m_ios)
|
, m_socket(m_ios)
|
||||||
, m_out_socket(m_ios)
|
, m_info_hash(0)
|
||||||
, m_tripped(false)
|
, m_accepted(false)
|
||||||
|
, m_connected(false)
|
||||||
|
, m_disconnected(false)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
m_acceptor.open(asio::ip::tcp::v4(), ec);
|
m_acceptor.open(asio::ip::tcp::v4(), ec);
|
||||||
|
@ -65,37 +67,46 @@ struct fake_peer
|
||||||
m_acceptor.listen(10, ec);
|
m_acceptor.listen(10, ec);
|
||||||
TEST_CHECK(!ec);
|
TEST_CHECK(!ec);
|
||||||
|
|
||||||
m_acceptor.async_accept(m_in_socket, [&] (boost::system::error_code const& ec)
|
m_acceptor.async_accept(m_socket, [&] (boost::system::error_code const& ec)
|
||||||
{
|
{
|
||||||
// TODO: ideally we would kick off a read on the socket to verify that
|
using namespace std::placeholders;
|
||||||
// we received a bittorrent handshake
|
if (ec) return;
|
||||||
if (!ec) m_tripped = true;
|
|
||||||
|
asio::async_read(m_socket, asio::mutable_buffers_1(&m_out_buffer[0], 68)
|
||||||
|
, std::bind(&fake_peer::read_handshake, this, _1, _2));
|
||||||
|
|
||||||
|
m_accepted = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void close()
|
void close()
|
||||||
{
|
{
|
||||||
m_acceptor.close();
|
m_acceptor.close();
|
||||||
m_in_socket.close();
|
m_socket.close();
|
||||||
m_out_socket.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void connect_to(asio::ip::tcp::endpoint ep, lt::sha1_hash const& ih)
|
void connect_to(asio::ip::tcp::endpoint ep, lt::sha1_hash const& ih)
|
||||||
{
|
{
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
m_info_hash = ih;
|
||||||
|
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
m_out_socket.async_connect(ep, std::bind(&fake_peer::write_handshake
|
m_socket.async_connect(ep, std::bind(&fake_peer::write_handshake
|
||||||
, this, _1, ih));
|
, this, _1, ih));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tripped() const { return m_tripped; }
|
bool accepted() const { return m_accepted; }
|
||||||
|
bool connected() const { return m_connected; }
|
||||||
|
bool disconnected() const { return m_disconnected; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void write_handshake(boost::system::error_code const& ec, lt::sha1_hash ih)
|
void write_handshake(boost::system::error_code const& ec, lt::sha1_hash ih)
|
||||||
{
|
{
|
||||||
asio::ip::tcp::endpoint ep = m_out_socket.remote_endpoint();
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
asio::ip::tcp::endpoint ep = m_socket.remote_endpoint();
|
||||||
std::printf("fake_peer::connect (%s) -> (%d) %s\n"
|
std::printf("fake_peer::connect (%s) -> (%d) %s\n"
|
||||||
, lt::print_endpoint(ep).c_str(), ec.value()
|
, lt::print_endpoint(ep).c_str(), ec.value()
|
||||||
, ec.message().c_str());
|
, ec.message().c_str());
|
||||||
|
@ -108,43 +119,140 @@ private:
|
||||||
memcpy(m_out_buffer, handshake, len);
|
memcpy(m_out_buffer, handshake, len);
|
||||||
memcpy(&m_out_buffer[28], ih.data(), 20);
|
memcpy(&m_out_buffer[28], ih.data(), 20);
|
||||||
|
|
||||||
asio::async_write(m_out_socket, asio::const_buffers_1(&m_out_buffer[0]
|
asio::async_write(m_socket, asio::const_buffers_1(&m_out_buffer[0]
|
||||||
, len), [=](boost::system::error_code const& ec, size_t bytes_transferred)
|
, len), [this, ep](boost::system::error_code const& ec, size_t bytes_transferred)
|
||||||
{
|
{
|
||||||
std::printf("fake_peer::write_handshake(%s) -> (%d) %s\n"
|
std::printf("fake_peer::write_handshake(%s) -> (%d) %s\n"
|
||||||
, lt::print_endpoint(ep).c_str(), ec.value()
|
, lt::print_endpoint(ep).c_str(), ec.value()
|
||||||
, ec.message().c_str());
|
, ec.message().c_str());
|
||||||
this->m_out_socket.close();
|
asio::async_read(m_socket, asio::mutable_buffers_1(&m_out_buffer[0], 68)
|
||||||
|
, std::bind(&fake_peer::read_handshake, this, _1, _2));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void read_handshake(lt::error_code const& ec, size_t bytes_transferred)
|
||||||
|
{
|
||||||
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
std::printf("fake_peer::read_handshake -> (%d) %s\n"
|
||||||
|
, ec.value(), ec.message().c_str());
|
||||||
|
if (ec)
|
||||||
|
{
|
||||||
|
m_socket.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(&m_out_buffer[0], "\x13" "BitTorrent protocol", 20) != 0)
|
||||||
|
{
|
||||||
|
std::printf(" invalid protocol specifier\n");
|
||||||
|
m_socket.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this peer accepted an incoming connection, we don't know what the
|
||||||
|
// info hash is supposed to be
|
||||||
|
if (!m_info_hash.is_all_zeros()
|
||||||
|
&& memcmp(&m_out_buffer[28], m_info_hash.data(), 20) != 0)
|
||||||
|
{
|
||||||
|
std::printf(" invalid info hash\n");
|
||||||
|
m_socket.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_connected = true;
|
||||||
|
|
||||||
|
// keep reading until we receie EOF, then set m_disconnected = true
|
||||||
|
m_socket.async_read_some(asio::mutable_buffers_1(&m_out_buffer[0]
|
||||||
|
, sizeof(m_out_buffer))
|
||||||
|
, std::bind(&fake_peer::on_read, this, _1, _2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_read(lt::error_code const& ec, size_t bytes_transferred)
|
||||||
|
{
|
||||||
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
std::printf("fake_peer::on_read -> (%d) %s\n"
|
||||||
|
, ec.value(), ec.message().c_str());
|
||||||
|
if (ec)
|
||||||
|
{
|
||||||
|
std::printf(" closing\n");
|
||||||
|
m_disconnected = true;
|
||||||
|
m_socket.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_socket.async_read_some(asio::mutable_buffers_1(&m_out_buffer[0]
|
||||||
|
, sizeof(m_out_buffer))
|
||||||
|
, std::bind(&fake_peer::on_read, this, _1, _2));
|
||||||
|
}
|
||||||
|
|
||||||
char m_out_buffer[300];
|
char m_out_buffer[300];
|
||||||
|
|
||||||
asio::io_service m_ios;
|
asio::io_service m_ios;
|
||||||
asio::ip::tcp::acceptor m_acceptor;
|
asio::ip::tcp::acceptor m_acceptor;
|
||||||
asio::ip::tcp::socket m_in_socket;
|
asio::ip::tcp::socket m_socket;
|
||||||
asio::ip::tcp::socket m_out_socket;
|
lt::sha1_hash m_info_hash;
|
||||||
bool m_tripped;
|
|
||||||
|
// set to true if this peer received an incoming connection
|
||||||
|
// if this is an outgoing connection, this will always be false
|
||||||
|
bool m_accepted;
|
||||||
|
|
||||||
|
// set to true if this peer completed a bittorrent handshake
|
||||||
|
bool m_connected;
|
||||||
|
|
||||||
|
// set to true if this peer has been disconnected by the other end
|
||||||
|
bool m_disconnected;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void add_fake_peers(lt::torrent_handle h)
|
inline void add_fake_peer(lt::torrent_handle& h, int const i)
|
||||||
|
{
|
||||||
|
char ep[30];
|
||||||
|
std::snprintf(ep, sizeof(ep), "60.0.0.%d", i);
|
||||||
|
h.connect_peer(lt::tcp::endpoint(
|
||||||
|
lt::address_v4::from_string(ep), 6881));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void add_fake_peers(lt::torrent_handle& h, int const n = 5)
|
||||||
{
|
{
|
||||||
// add the fake peers
|
// add the fake peers
|
||||||
for (int i = 0; i < 5; ++i)
|
for (int i = 0; i < n; ++i)
|
||||||
{
|
{
|
||||||
char ep[30];
|
add_fake_peer(h, i);
|
||||||
std::snprintf(ep, sizeof(ep), "60.0.0.%d", i);
|
|
||||||
h.connect_peer(lt::tcp::endpoint(
|
|
||||||
lt::address_v4::from_string(ep), 6881));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void check_tripped(std::array<fake_peer*, 5>& test_peers, std::array<bool, 5> expected)
|
template<unsigned long N>
|
||||||
|
void check_accepted(std::array<fake_peer*, N>& test_peers
|
||||||
|
, std::array<bool, N> expected)
|
||||||
{
|
{
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
for (auto p : test_peers)
|
for (auto p : test_peers)
|
||||||
{
|
{
|
||||||
TEST_EQUAL(p->tripped(), expected[idx]);
|
TEST_EQUAL(p->accepted(), expected[idx]);
|
||||||
|
++idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned long N>
|
||||||
|
void check_connected(std::array<fake_peer*, N>& test_peers
|
||||||
|
, std::array<bool, N> expected)
|
||||||
|
{
|
||||||
|
int idx = 0;
|
||||||
|
for (auto p : test_peers)
|
||||||
|
{
|
||||||
|
TEST_EQUAL(p->connected(), expected[idx]);
|
||||||
|
++idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned long N>
|
||||||
|
void check_disconnected(std::array<fake_peer*, N>& test_peers
|
||||||
|
, std::array<bool, N> expected)
|
||||||
|
{
|
||||||
|
int idx = 0;
|
||||||
|
for (auto p : test_peers)
|
||||||
|
{
|
||||||
|
TEST_EQUAL(p->disconnected(), expected[idx]);
|
||||||
++idx;
|
++idx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/alert_types.hpp"
|
#include "libtorrent/alert_types.hpp"
|
||||||
#include "libtorrent/deadline_timer.hpp"
|
#include "libtorrent/deadline_timer.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
#include "utils.hpp"
|
||||||
#include "create_torrent.hpp"
|
#include "create_torrent.hpp"
|
||||||
#include "simulator/simulator.hpp"
|
#include "simulator/simulator.hpp"
|
||||||
#include "simulator/utils.hpp"
|
#include "simulator/utils.hpp"
|
||||||
|
@ -49,14 +50,6 @@ namespace lt = libtorrent;
|
||||||
|
|
||||||
using sim::asio::ip::address_v4;
|
using sim::asio::ip::address_v4;
|
||||||
|
|
||||||
std::unique_ptr<sim::asio::io_service> make_io_service(sim::simulation& sim, int i)
|
|
||||||
{
|
|
||||||
char ep[30];
|
|
||||||
std::snprintf(ep, sizeof(ep), "50.0.%d.%d", (i + 1) >> 8, (i + 1) & 0xff);
|
|
||||||
return std::unique_ptr<sim::asio::io_service>(new sim::asio::io_service(
|
|
||||||
sim, asio::ip::address_v4::from_string(ep)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is the general template for these tests. create the session with custom
|
// this is the general template for these tests. create the session with custom
|
||||||
// settings (Settings), set up the test, by adding torrents with certain
|
// settings (Settings), set up the test, by adding torrents with certain
|
||||||
// arguments (Setup), run the test and verify the end state (Test)
|
// arguments (Setup), run the test and verify the end state (Test)
|
||||||
|
|
|
@ -137,7 +137,7 @@ TORRENT_TEST(apply_ip_filter)
|
||||||
|
|
||||||
[](lt::session& ses, std::array<fake_peer*, 5>& test_peers)
|
[](lt::session& ses, std::array<fake_peer*, 5>& test_peers)
|
||||||
{
|
{
|
||||||
check_tripped(test_peers, {{false, false, false, true, true}} );
|
check_accepted(test_peers, {{false, false, false, true, true}} );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,7 @@ TORRENT_TEST(update_ip_filter)
|
||||||
|
|
||||||
[](lt::session& ses, std::array<fake_peer*, 5>& test_peers)
|
[](lt::session& ses, std::array<fake_peer*, 5>& test_peers)
|
||||||
{
|
{
|
||||||
check_tripped(test_peers, {{false, false, false, true, true}} );
|
check_accepted(test_peers, {{false, false, false, true, true}} );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -204,7 +204,7 @@ TORRENT_TEST(apply_ip_filter_to_torrent)
|
||||||
{
|
{
|
||||||
// since the IP filter didn't apply to this torrent, it should have hit
|
// since the IP filter didn't apply to this torrent, it should have hit
|
||||||
// all peers
|
// all peers
|
||||||
check_tripped(test_peers, {{true, true, true, true, true}} );
|
check_accepted(test_peers, {{true, true, true, true, true}} );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -233,7 +233,7 @@ TORRENT_TEST(ip_filter_trackers)
|
||||||
[](lt::session& ses, lt::alert const* a) {},
|
[](lt::session& ses, lt::alert const* a) {},
|
||||||
[](lt::session& ses, std::array<fake_peer*, 5>& test_peers)
|
[](lt::session& ses, std::array<fake_peer*, 5>& test_peers)
|
||||||
{
|
{
|
||||||
check_tripped(test_peers, {{false, false, false, true, true}} );
|
check_accepted(test_peers, {{false, false, false, true, true}} );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,337 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libtorrent/session.hpp"
|
||||||
|
#include "libtorrent/torrent_handle.hpp"
|
||||||
|
#include "libtorrent/settings_pack.hpp"
|
||||||
|
#include "libtorrent/alert_types.hpp"
|
||||||
|
#include "libtorrent/deadline_timer.hpp"
|
||||||
|
#include "settings.hpp"
|
||||||
|
#include "fake_peer.hpp"
|
||||||
|
#include "utils.hpp"
|
||||||
|
#include "create_torrent.hpp"
|
||||||
|
#include "simulator/simulator.hpp"
|
||||||
|
#include "simulator/utils.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace sim;
|
||||||
|
using namespace libtorrent;
|
||||||
|
|
||||||
|
namespace lt = libtorrent;
|
||||||
|
|
||||||
|
using sim::asio::ip::address_v4;
|
||||||
|
|
||||||
|
// this is the general template for these tests. create the session with custom
|
||||||
|
// settings (Settings), set up the test, by adding torrents with certain
|
||||||
|
// arguments (Setup), run the test and verify the end state (Test)
|
||||||
|
template <typename Setup, typename Torrent, typename Test, typename Check>
|
||||||
|
void run_test(Setup const& setup, Torrent const& torrent
|
||||||
|
, Test const& test, Check const& check)
|
||||||
|
{
|
||||||
|
// setup the simulation
|
||||||
|
sim::default_config network_cfg;
|
||||||
|
sim::simulation sim{network_cfg};
|
||||||
|
std::unique_ptr<sim::asio::io_service> ios = make_io_service(sim, 0);
|
||||||
|
lt::session_proxy zombie;
|
||||||
|
|
||||||
|
// setup settings pack to use for the session (customization point)
|
||||||
|
lt::settings_pack pack = settings();
|
||||||
|
|
||||||
|
// create session
|
||||||
|
std::shared_ptr<lt::session> ses = std::make_shared<lt::session>(pack, *ios);
|
||||||
|
|
||||||
|
setup(*ses);
|
||||||
|
|
||||||
|
fake_peer p1(sim, "60.0.0.0");
|
||||||
|
fake_peer p2(sim, "60.0.0.1");
|
||||||
|
fake_peer p3(sim, "60.0.0.2");
|
||||||
|
std::array<fake_peer*, 3> test_peers = {{ &p1, &p2, &p3 }};
|
||||||
|
|
||||||
|
// add torrent
|
||||||
|
lt::add_torrent_params params = create_torrent(0, false);
|
||||||
|
params.flags &= ~lt::add_torrent_params::flag_auto_managed;
|
||||||
|
params.flags &= ~lt::add_torrent_params::flag_paused;
|
||||||
|
ses->async_add_torrent(params);
|
||||||
|
|
||||||
|
lt::torrent_handle h;
|
||||||
|
print_alerts(*ses, [&](lt::session& ses, lt::alert const* a) {
|
||||||
|
auto at = lt::alert_cast<torrent_added_alert>(a);
|
||||||
|
if (at == nullptr) return;
|
||||||
|
h = at->handle;
|
||||||
|
|
||||||
|
// disable the print_alert object from polling any more alerts
|
||||||
|
ses.set_alert_notify([]{});
|
||||||
|
|
||||||
|
torrent(ses, h, test_peers);
|
||||||
|
});
|
||||||
|
|
||||||
|
sim::timer t1(sim, lt::seconds(5)
|
||||||
|
, [&](boost::system::error_code const& ec)
|
||||||
|
{
|
||||||
|
test(*ses, h, test_peers);
|
||||||
|
});
|
||||||
|
|
||||||
|
// set up a timer to fire later, to verify everything we expected to happen
|
||||||
|
// happened
|
||||||
|
sim::timer t2(sim, lt::seconds(10)
|
||||||
|
, [&](boost::system::error_code const& ec)
|
||||||
|
{
|
||||||
|
check(*ses, h, test_peers);
|
||||||
|
|
||||||
|
// shut down
|
||||||
|
zombie = ses->abort();
|
||||||
|
ses.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
sim.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the torrent disconnects all its peers when it's paused
|
||||||
|
TORRENT_TEST(torrent_paused_disconnect)
|
||||||
|
{
|
||||||
|
run_test(
|
||||||
|
[](lt::session& ses) {},
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
add_fake_peers(h, 3);
|
||||||
|
},
|
||||||
|
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
check_accepted(test_peers, {{true, true, true}});
|
||||||
|
check_connected(test_peers, {{true, true, true}});
|
||||||
|
check_disconnected(test_peers, {{false, false, false}});
|
||||||
|
h.pause();
|
||||||
|
},
|
||||||
|
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
check_disconnected(test_peers, {{true, true, true}});
|
||||||
|
TEST_EQUAL(h.status().paused, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the torrent disconnects all its peers when the session is paused
|
||||||
|
TORRENT_TEST(session_paused_disconnect)
|
||||||
|
{
|
||||||
|
run_test(
|
||||||
|
[](lt::session& ses) {},
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
add_fake_peers(h, 3);
|
||||||
|
},
|
||||||
|
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
check_accepted(test_peers, {{true, true, true}});
|
||||||
|
check_connected(test_peers, {{true, true, true}});
|
||||||
|
check_disconnected(test_peers, {{false, false, false}});
|
||||||
|
ses.pause();
|
||||||
|
},
|
||||||
|
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
check_disconnected(test_peers, {{true, true, true}});
|
||||||
|
|
||||||
|
// the torrent isn't paused, the session is
|
||||||
|
TEST_EQUAL(h.status().paused, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure a torrent is not connecting to any peers when added to a paused
|
||||||
|
// session
|
||||||
|
TORRENT_TEST(paused_session_add_torrent)
|
||||||
|
{
|
||||||
|
run_test(
|
||||||
|
[](lt::session& ses) { ses.pause(); },
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
add_fake_peers(h, 3);
|
||||||
|
},
|
||||||
|
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
check_accepted(test_peers, {{false, false, false}});
|
||||||
|
},
|
||||||
|
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
// the torrent isn't paused, the session is
|
||||||
|
TEST_EQUAL(h.status().paused, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the torrent isn't connecting to peers when it's paused
|
||||||
|
TORRENT_TEST(paused_torrent_add_peers)
|
||||||
|
{
|
||||||
|
run_test(
|
||||||
|
[](lt::session& ses) {},
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
h.pause();
|
||||||
|
|
||||||
|
add_fake_peers(h, 3);
|
||||||
|
},
|
||||||
|
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
check_accepted(test_peers, {{false, false, false}});
|
||||||
|
},
|
||||||
|
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
TEST_EQUAL(h.status().paused, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure we post the torrent_paused alert when pausing a torrent
|
||||||
|
TORRENT_TEST(torrent_paused_alert)
|
||||||
|
{
|
||||||
|
run_test(
|
||||||
|
[](lt::session& ses) {},
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {},
|
||||||
|
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
TEST_EQUAL(h.status().paused, false);
|
||||||
|
h.pause();
|
||||||
|
},
|
||||||
|
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
TEST_EQUAL(h.status().paused, true);
|
||||||
|
|
||||||
|
std::vector<lt::alert*> alerts;
|
||||||
|
ses.pop_alerts(&alerts);
|
||||||
|
|
||||||
|
lt::time_point start_time = alerts[0]->timestamp();
|
||||||
|
|
||||||
|
int num_resume = 0;
|
||||||
|
int num_paused = 0;
|
||||||
|
for (alert* a : alerts)
|
||||||
|
{
|
||||||
|
std::printf("%-3d %s\n", int(duration_cast<lt::seconds>(a->timestamp()
|
||||||
|
- start_time).count()), a->message().c_str());
|
||||||
|
if (lt::alert_cast<torrent_resumed_alert>(a)) ++num_resume;
|
||||||
|
if (lt::alert_cast<torrent_paused_alert>(a)) ++num_paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_EQUAL(num_resume, 0);
|
||||||
|
TEST_EQUAL(num_paused, 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure we post the torrent_paused alert when pausing the session
|
||||||
|
TORRENT_TEST(session_paused_alert)
|
||||||
|
{
|
||||||
|
run_test(
|
||||||
|
[](lt::session& ses) {},
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {},
|
||||||
|
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
TEST_EQUAL(h.status().paused, false);
|
||||||
|
ses.pause();
|
||||||
|
},
|
||||||
|
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
TEST_EQUAL(h.status().paused, false);
|
||||||
|
|
||||||
|
std::vector<lt::alert*> alerts;
|
||||||
|
ses.pop_alerts(&alerts);
|
||||||
|
|
||||||
|
lt::time_point start_time = alerts[0]->timestamp();
|
||||||
|
|
||||||
|
int num_resume = 0;
|
||||||
|
int num_paused = 0;
|
||||||
|
for (alert* a : alerts)
|
||||||
|
{
|
||||||
|
std::printf("%-3d %s\n", int(duration_cast<lt::seconds>(a->timestamp()
|
||||||
|
- start_time).count()), a->message().c_str());
|
||||||
|
if (lt::alert_cast<torrent_resumed_alert>(a)) ++num_resume;
|
||||||
|
if (lt::alert_cast<torrent_paused_alert>(a)) ++num_paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_EQUAL(num_resume, 0);
|
||||||
|
TEST_EQUAL(num_paused, 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure we post both the paused and resumed alert when pausing and resuming
|
||||||
|
// the session.
|
||||||
|
TORRENT_TEST(session_pause_resume)
|
||||||
|
{
|
||||||
|
run_test(
|
||||||
|
[](lt::session& ses) {},
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
TEST_EQUAL(h.status().paused, false);
|
||||||
|
ses.pause();
|
||||||
|
},
|
||||||
|
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
TEST_EQUAL(h.status().paused, false);
|
||||||
|
ses.resume();
|
||||||
|
},
|
||||||
|
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
TEST_EQUAL(h.status().paused, false);
|
||||||
|
|
||||||
|
std::vector<lt::alert*> alerts;
|
||||||
|
ses.pop_alerts(&alerts);
|
||||||
|
|
||||||
|
lt::time_point start_time = alerts[0]->timestamp();
|
||||||
|
|
||||||
|
int num_resume = 0;
|
||||||
|
int num_paused = 0;
|
||||||
|
for (alert* a : alerts)
|
||||||
|
{
|
||||||
|
std::printf("%-3d %s\n", int(duration_cast<lt::seconds>(a->timestamp()
|
||||||
|
- start_time).count()), a->message().c_str());
|
||||||
|
if (lt::alert_cast<torrent_resumed_alert>(a)) ++num_resume;
|
||||||
|
if (lt::alert_cast<torrent_paused_alert>(a)) ++num_paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_EQUAL(num_resume, 1);
|
||||||
|
TEST_EQUAL(num_paused, 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure peers added to a (non-paused) torrent in a paused session are
|
||||||
|
// connected once the session is resumed
|
||||||
|
TORRENT_TEST(session_pause_resume_connect)
|
||||||
|
{
|
||||||
|
run_test(
|
||||||
|
[](lt::session& ses) {},
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
TEST_EQUAL(h.status().paused, false);
|
||||||
|
ses.pause();
|
||||||
|
add_fake_peers(h, 3);
|
||||||
|
},
|
||||||
|
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
TEST_EQUAL(h.status().paused, false);
|
||||||
|
check_accepted(test_peers, {{false, false, false}});
|
||||||
|
ses.resume();
|
||||||
|
},
|
||||||
|
|
||||||
|
[](lt::session& ses, lt::torrent_handle h, std::array<fake_peer*, 3>& test_peers) {
|
||||||
|
TEST_EQUAL(h.status().paused, false);
|
||||||
|
|
||||||
|
check_accepted(test_peers, {{true, true, true}});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -51,14 +51,6 @@ using namespace libtorrent;
|
||||||
|
|
||||||
namespace lt = libtorrent;
|
namespace lt = libtorrent;
|
||||||
|
|
||||||
std::unique_ptr<sim::asio::io_service> make_io_service(sim::simulation& sim, int i)
|
|
||||||
{
|
|
||||||
char ep[30];
|
|
||||||
std::snprintf(ep, sizeof(ep), "50.0.%d.%d", (i + 1) >> 8, (i + 1) & 0xff);
|
|
||||||
return std::unique_ptr<sim::asio::io_service>(new sim::asio::io_service(
|
|
||||||
sim, address_v4::from_string(ep)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is the general template for these tests. create the session with custom
|
// this is the general template for these tests. create the session with custom
|
||||||
// settings (Settings), set up the test, by adding torrents with certain
|
// settings (Settings), set up the test, by adding torrents with certain
|
||||||
// arguments (Setup), run the test and verify the end state (Test)
|
// arguments (Setup), run the test and verify the end state (Test)
|
||||||
|
|
|
@ -39,6 +39,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/alert_types.hpp"
|
#include "libtorrent/alert_types.hpp"
|
||||||
#include "libtorrent/session_stats.hpp"
|
#include "libtorrent/session_stats.hpp"
|
||||||
#include "libtorrent/alert.hpp"
|
#include "libtorrent/alert.hpp"
|
||||||
|
#include "libtorrent/io_service.hpp"
|
||||||
#include "setup_swarm.hpp"
|
#include "setup_swarm.hpp"
|
||||||
|
|
||||||
using namespace libtorrent;
|
using namespace libtorrent;
|
||||||
|
@ -142,3 +143,11 @@ void print_alerts(lt::session& ses
|
||||||
} ); } );
|
} ); } );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<sim::asio::io_service> make_io_service(sim::simulation& sim, int i)
|
||||||
|
{
|
||||||
|
char ep[30];
|
||||||
|
std::snprintf(ep, sizeof(ep), "50.0.%d.%d", (i + 1) >> 8, (i + 1) & 0xff);
|
||||||
|
return std::unique_ptr<sim::asio::io_service>(new sim::asio::io_service(
|
||||||
|
sim, lt::address_v4::from_string(ep)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,9 @@ void filter_ips(lt::session& ses);
|
||||||
void set_cache_size(lt::session& ses, int val);
|
void set_cache_size(lt::session& ses, int val);
|
||||||
int get_cache_size(lt::session& ses);
|
int get_cache_size(lt::session& ses);
|
||||||
|
|
||||||
|
std::unique_ptr<sim::asio::io_service> make_io_service(
|
||||||
|
sim::simulation& sim, int i);
|
||||||
|
|
||||||
enum flags_t
|
enum flags_t
|
||||||
{
|
{
|
||||||
ipv6 = 1,
|
ipv6 = 1,
|
||||||
|
|
|
@ -851,11 +851,9 @@ namespace aux {
|
||||||
session_log(" *** session paused ***");
|
session_log(" *** session paused ***");
|
||||||
#endif
|
#endif
|
||||||
m_paused = true;
|
m_paused = true;
|
||||||
for (torrent_map::iterator i = m_torrents.begin()
|
for (auto& te : m_torrents)
|
||||||
, end(m_torrents.end()); i != end; ++i)
|
|
||||||
{
|
{
|
||||||
torrent& t = *i->second;
|
te.second->set_session_paused(true);
|
||||||
t.do_pause();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -865,12 +863,10 @@ namespace aux {
|
||||||
|
|
||||||
if (!m_paused) return;
|
if (!m_paused) return;
|
||||||
m_paused = false;
|
m_paused = false;
|
||||||
for (torrent_map::iterator i = m_torrents.begin()
|
|
||||||
, end(m_torrents.end()); i != end; ++i)
|
for (auto& te : m_torrents)
|
||||||
{
|
{
|
||||||
torrent& t = *i->second;
|
te.second->set_session_paused(false);
|
||||||
t.do_resume();
|
|
||||||
if (t.should_check_files()) t.start_checking();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3293,7 +3289,7 @@ namespace aux {
|
||||||
// scrape paused torrents that are auto managed
|
// scrape paused torrents that are auto managed
|
||||||
// (unless the session is paused)
|
// (unless the session is paused)
|
||||||
// --------------------------------------------------------------
|
// --------------------------------------------------------------
|
||||||
if (!is_paused())
|
if (!m_paused)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
--m_auto_scrape_time_scaler;
|
--m_auto_scrape_time_scaler;
|
||||||
|
@ -3663,8 +3659,6 @@ namespace aux {
|
||||||
t->log_to_all_peers("auto manager starting (inactive) torrent");
|
t->log_to_all_peers("auto manager starting (inactive) torrent");
|
||||||
#endif
|
#endif
|
||||||
t->set_paused(false);
|
t->set_paused(false);
|
||||||
t->update_gauge();
|
|
||||||
t->update_want_peers();
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3681,8 +3675,6 @@ namespace aux {
|
||||||
t->log_to_all_peers("auto manager starting torrent");
|
t->log_to_all_peers("auto manager starting torrent");
|
||||||
#endif
|
#endif
|
||||||
t->set_paused(false);
|
t->set_paused(false);
|
||||||
t->update_gauge();
|
|
||||||
t->update_want_peers();
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3696,8 +3688,6 @@ namespace aux {
|
||||||
t->set_announce_to_dht(false);
|
t->set_announce_to_dht(false);
|
||||||
t->set_announce_to_trackers(false);
|
t->set_announce_to_trackers(false);
|
||||||
t->set_announce_to_lsd(false);
|
t->set_announce_to_lsd(false);
|
||||||
t->update_gauge();
|
|
||||||
t->update_want_peers();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3715,7 +3705,7 @@ namespace aux {
|
||||||
m_last_auto_manage = time_now();
|
m_last_auto_manage = time_now();
|
||||||
m_need_auto_manage = false;
|
m_need_auto_manage = false;
|
||||||
|
|
||||||
if (is_paused()) return;
|
if (m_paused) return;
|
||||||
|
|
||||||
// make copies of the lists of torrents that we want to consider for auto
|
// make copies of the lists of torrents that we want to consider for auto
|
||||||
// management. We need copies because they will be sorted.
|
// management. We need copies because they will be sorted.
|
||||||
|
@ -4908,7 +4898,8 @@ namespace aux {
|
||||||
int queue_pos = ++m_max_queue_pos;
|
int queue_pos = ++m_max_queue_pos;
|
||||||
|
|
||||||
torrent_ptr = boost::make_shared<torrent>(boost::ref(*this)
|
torrent_ptr = boost::make_shared<torrent>(boost::ref(*this)
|
||||||
, 16 * 1024, queue_pos, boost::cref(params), boost::cref(params.info_hash));
|
, 16 * 1024, queue_pos, m_paused
|
||||||
|
, boost::cref(params), boost::cref(params.info_hash));
|
||||||
|
|
||||||
return torrent_ptr;
|
return torrent_ptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,13 +168,15 @@ namespace libtorrent
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
torrent_hot_members::torrent_hot_members(aux::session_interface& ses
|
torrent_hot_members::torrent_hot_members(aux::session_interface& ses
|
||||||
, add_torrent_params const& p, int block_size)
|
, add_torrent_params const& p, int const block_size
|
||||||
|
, bool const session_paused)
|
||||||
: m_ses(ses)
|
: m_ses(ses)
|
||||||
, m_complete(0xffffff)
|
, m_complete(0xffffff)
|
||||||
, m_upload_mode((p.flags & add_torrent_params::flag_upload_mode) != 0)
|
, m_upload_mode((p.flags & add_torrent_params::flag_upload_mode) != 0)
|
||||||
, m_connections_initialized(false)
|
, m_connections_initialized(false)
|
||||||
, m_abort(false)
|
, m_abort(false)
|
||||||
, m_paused((p.flags & add_torrent_params::flag_paused) != 0)
|
, m_paused((p.flags & add_torrent_params::flag_paused) != 0)
|
||||||
|
, m_session_paused(session_paused)
|
||||||
, m_share_mode((p.flags & add_torrent_params::flag_share_mode) != 0)
|
, m_share_mode((p.flags & add_torrent_params::flag_share_mode) != 0)
|
||||||
, m_have_all(false)
|
, m_have_all(false)
|
||||||
, m_graceful_pause_mode(false)
|
, m_graceful_pause_mode(false)
|
||||||
|
@ -186,11 +188,12 @@ namespace libtorrent
|
||||||
|
|
||||||
torrent::torrent(
|
torrent::torrent(
|
||||||
aux::session_interface& ses
|
aux::session_interface& ses
|
||||||
, int block_size
|
, int const block_size
|
||||||
, int seq
|
, int const seq
|
||||||
|
, bool const session_paused
|
||||||
, add_torrent_params const& p
|
, add_torrent_params const& p
|
||||||
, sha1_hash const& info_hash)
|
, sha1_hash const& info_hash)
|
||||||
: torrent_hot_members(ses, p, block_size)
|
: torrent_hot_members(ses, p, block_size, session_paused)
|
||||||
, m_total_uploaded(0)
|
, m_total_uploaded(0)
|
||||||
, m_total_downloaded(0)
|
, m_total_downloaded(0)
|
||||||
, m_tracker_timer(ses.get_io_service())
|
, m_tracker_timer(ses.get_io_service())
|
||||||
|
@ -322,19 +325,18 @@ namespace libtorrent
|
||||||
bool const multi_file = m_torrent_file->is_valid()
|
bool const multi_file = m_torrent_file->is_valid()
|
||||||
&& m_torrent_file->num_files() > 1;
|
&& m_torrent_file->num_files() > 1;
|
||||||
|
|
||||||
for (std::vector<std::string>::const_iterator i = p.url_seeds.begin()
|
for (auto const& u : p.url_seeds)
|
||||||
, end(p.url_seeds.end()); i != end; ++i)
|
|
||||||
{
|
{
|
||||||
m_web_seeds.push_back(web_seed_t(*i, web_seed_entry::url_seed));
|
m_web_seeds.push_back(web_seed_t(u, web_seed_entry::url_seed));
|
||||||
|
|
||||||
// correct URLs to end with a "/" for multi-file torrents
|
// correct URLs to end with a "/" for multi-file torrents
|
||||||
std::string& url = m_web_seeds.back().url;
|
std::string& url = m_web_seeds.back().url;
|
||||||
if (multi_file && url[url.size()-1] != '/') url += '/';
|
if (multi_file && url[url.size()-1] != '/') url += '/';
|
||||||
}
|
}
|
||||||
for (std::vector<std::string>::const_iterator i = p.http_seeds.begin()
|
|
||||||
, end(p.http_seeds.end()); i != end; ++i)
|
for (auto const& e : p.http_seeds)
|
||||||
{
|
{
|
||||||
m_web_seeds.push_back(web_seed_t(*i, web_seed_entry::http_seed));
|
m_web_seeds.push_back(web_seed_t(e, web_seed_entry::http_seed));
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- TRACKERS ---
|
// --- TRACKERS ---
|
||||||
|
@ -346,14 +348,12 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
int tier = 0;
|
int tier = 0;
|
||||||
std::vector<int>::const_iterator tier_iter = p.tracker_tiers.begin();
|
auto tier_iter = p.tracker_tiers.begin();
|
||||||
for (std::vector<std::string>::const_iterator i = p.trackers.begin()
|
for (announce_entry e : p.trackers)
|
||||||
, end(p.trackers.end()); i != end; ++i)
|
|
||||||
{
|
{
|
||||||
if (tier_iter != p.tracker_tiers.end())
|
if (tier_iter != p.tracker_tiers.end())
|
||||||
tier = *tier_iter++;
|
tier = *tier_iter++;
|
||||||
|
|
||||||
announce_entry e(*i);
|
|
||||||
e.fail_limit = 0;
|
e.fail_limit = 0;
|
||||||
e.source = announce_entry::source_magnet_link;
|
e.source = announce_entry::source_magnet_link;
|
||||||
e.tier = tier;
|
e.tier = tier;
|
||||||
|
@ -8941,7 +8941,7 @@ namespace libtorrent
|
||||||
&& !has_error()
|
&& !has_error()
|
||||||
&& !m_abort
|
&& !m_abort
|
||||||
&& !m_graceful_pause_mode
|
&& !m_graceful_pause_mode
|
||||||
&& !m_ses.is_paused();
|
&& !m_session_paused;
|
||||||
}
|
}
|
||||||
|
|
||||||
void torrent::flush_cache()
|
void torrent::flush_cache()
|
||||||
|
@ -8972,7 +8972,7 @@ namespace libtorrent
|
||||||
|
|
||||||
bool torrent::is_paused() const
|
bool torrent::is_paused() const
|
||||||
{
|
{
|
||||||
return m_paused || m_ses.is_paused() || m_graceful_pause_mode;
|
return m_paused || m_session_paused || m_graceful_pause_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void torrent::pause(bool graceful)
|
void torrent::pause(bool graceful)
|
||||||
|
@ -9028,9 +9028,15 @@ namespace libtorrent
|
||||||
if (is_finished())
|
if (is_finished())
|
||||||
m_finished_time += m_ses.session_time() - m_became_finished;
|
m_finished_time += m_ses.session_time() - m_became_finished;
|
||||||
|
|
||||||
|
m_announce_to_dht = false;
|
||||||
|
m_announce_to_trackers = false;
|
||||||
|
m_announce_to_lsd = false;
|
||||||
|
|
||||||
state_updated();
|
state_updated();
|
||||||
update_want_peers();
|
update_want_peers();
|
||||||
update_want_scrape();
|
update_want_scrape();
|
||||||
|
update_gauge();
|
||||||
|
update_state_list();
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
log_to_all_peers("pausing");
|
log_to_all_peers("pausing");
|
||||||
|
@ -9055,7 +9061,7 @@ namespace libtorrent
|
||||||
// files and flush all cached data
|
// files and flush all cached data
|
||||||
if (m_storage.get() && clear_disk_cache)
|
if (m_storage.get() && clear_disk_cache)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(m_storage);
|
// the torrent_paused alert will be posted from on_torrent_paused
|
||||||
m_ses.disk_thread().async_stop_torrent(m_storage.get()
|
m_ses.disk_thread().async_stop_torrent(m_storage.get()
|
||||||
, std::bind(&torrent::on_torrent_paused, shared_from_this(), _1));
|
, std::bind(&torrent::on_torrent_paused, shared_from_this(), _1));
|
||||||
}
|
}
|
||||||
|
@ -9073,10 +9079,8 @@ namespace libtorrent
|
||||||
// and choke all remaining peers to prevent responding to new
|
// and choke all remaining peers to prevent responding to new
|
||||||
// requests
|
// requests
|
||||||
std::vector<peer_connection*> to_disconnect;
|
std::vector<peer_connection*> to_disconnect;
|
||||||
for (peer_iterator i = m_connections.begin();
|
for (peer_connection* p : m_connections)
|
||||||
i != m_connections.end(); ++i)
|
|
||||||
{
|
{
|
||||||
peer_connection* p = *i;
|
|
||||||
TORRENT_ASSERT(p->associated_torrent().lock().get() == this);
|
TORRENT_ASSERT(p->associated_torrent().lock().get() == this);
|
||||||
|
|
||||||
if (p->is_disconnecting()) continue;
|
if (p->is_disconnecting()) continue;
|
||||||
|
@ -9095,10 +9099,9 @@ namespace libtorrent
|
||||||
|
|
||||||
to_disconnect.push_back(p);
|
to_disconnect.push_back(p);
|
||||||
}
|
}
|
||||||
for (peer_iterator i = to_disconnect.begin(); i != to_disconnect.end(); ++i)
|
|
||||||
{
|
|
||||||
peer_connection* p = *i;
|
|
||||||
|
|
||||||
|
for (peer_connection* p : to_disconnect)
|
||||||
|
{
|
||||||
// since we're currently in graceful pause mode, the last peer to
|
// since we're currently in graceful pause mode, the last peer to
|
||||||
// disconnect (assuming all peers end up begin disconnected here)
|
// disconnect (assuming all peers end up begin disconnected here)
|
||||||
// will post the torrent_paused_alert
|
// will post the torrent_paused_alert
|
||||||
|
@ -9146,6 +9149,18 @@ namespace libtorrent
|
||||||
set_need_save_resume();
|
set_need_save_resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void torrent::set_session_paused(bool const b)
|
||||||
|
{
|
||||||
|
if (m_session_paused == b) return;
|
||||||
|
bool const paused_before = is_paused();
|
||||||
|
m_session_paused = b;
|
||||||
|
|
||||||
|
if (paused_before == is_paused()) return;
|
||||||
|
|
||||||
|
if (b) do_pause();
|
||||||
|
else do_resume();
|
||||||
|
}
|
||||||
|
|
||||||
void torrent::set_paused(bool b, int flags)
|
void torrent::set_paused(bool b, int flags)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(is_single_thread());
|
TORRENT_ASSERT(is_single_thread());
|
||||||
|
@ -9174,32 +9189,16 @@ namespace libtorrent
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool const paused_before = is_paused();
|
||||||
|
|
||||||
m_paused = b;
|
m_paused = b;
|
||||||
if (!m_ses.is_paused())
|
|
||||||
m_graceful_pause_mode = (flags & flag_graceful_pause) ? true : false;
|
|
||||||
|
|
||||||
if (b)
|
if (paused_before == is_paused()) return;
|
||||||
{
|
|
||||||
m_announce_to_dht = false;
|
|
||||||
m_announce_to_trackers = false;
|
|
||||||
m_announce_to_lsd = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
update_gauge();
|
m_graceful_pause_mode = (flags & flag_graceful_pause) ? true : false;
|
||||||
update_want_scrape();
|
|
||||||
update_want_peers();
|
|
||||||
update_state_list();
|
|
||||||
state_updated();
|
|
||||||
|
|
||||||
if (b)
|
|
||||||
{
|
|
||||||
do_pause((flags & flag_clear_disk_cache) != 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
do_resume();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (b) do_pause((flags & flag_clear_disk_cache) != 0);
|
||||||
|
else do_resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
void torrent::resume()
|
void torrent::resume()
|
||||||
|
@ -9216,7 +9215,7 @@ namespace libtorrent
|
||||||
m_announce_to_trackers = true;
|
m_announce_to_trackers = true;
|
||||||
m_announce_to_lsd = true;
|
m_announce_to_lsd = true;
|
||||||
m_paused = false;
|
m_paused = false;
|
||||||
if (!m_ses.is_paused()) m_graceful_pause_mode = false;
|
if (!m_session_paused) m_graceful_pause_mode = false;
|
||||||
|
|
||||||
update_gauge();
|
update_gauge();
|
||||||
|
|
||||||
|
@ -9265,6 +9264,9 @@ namespace libtorrent
|
||||||
update_want_peers();
|
update_want_peers();
|
||||||
update_want_tick();
|
update_want_tick();
|
||||||
update_want_scrape();
|
update_want_scrape();
|
||||||
|
update_gauge();
|
||||||
|
|
||||||
|
if (should_check_files()) start_checking();
|
||||||
|
|
||||||
if (m_state == torrent_status::checking_files) return;
|
if (m_state == torrent_status::checking_files) return;
|
||||||
|
|
||||||
|
@ -9837,8 +9839,8 @@ namespace libtorrent
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// now, pick one of the rarest pieces to download
|
// now, pick one of the rarest pieces to download
|
||||||
int pick = random() % rarest_pieces.size();
|
int const pick = random() % rarest_pieces.size();
|
||||||
bool was_finished = is_finished();
|
bool const was_finished = is_finished();
|
||||||
m_picker->set_piece_priority(rarest_pieces[pick], 1);
|
m_picker->set_piece_priority(rarest_pieces[pick], 1);
|
||||||
update_gauge();
|
update_gauge();
|
||||||
update_peer_interest(was_finished);
|
update_peer_interest(was_finished);
|
||||||
|
|
Loading…
Reference in New Issue