support building libtorrent in simulation mode (using libsimulator, which is a git submodule)
This commit is contained in:
parent
1cbd9a9d5e
commit
46803b75f8
8
Jamfile
8
Jamfile
|
@ -80,6 +80,11 @@ rule linking ( properties * )
|
|||
}
|
||||
}
|
||||
|
||||
if <simulator>on in $(properties)
|
||||
{
|
||||
result += <library>/libsimulator//simulator ;
|
||||
}
|
||||
|
||||
# dbghelp doesn't appear to exist in mingw
|
||||
if <target-os>windows in $(properties)
|
||||
&& ! <toolset>gcc in $(properties)
|
||||
|
@ -428,6 +433,9 @@ feature.compose <asio-debugging>on : <define>TORRENT_ASIO_DEBUGGING ;
|
|||
feature picker-debugging : off on : composite propagated link-incompatible ;
|
||||
feature.compose <picker-debugging>on : <define>TORRENT_DEBUG_REFCOUNTS ;
|
||||
|
||||
feature simulator : off on : composite propagated link-incompatible ;
|
||||
feature.compose <simulator>on : <define>TORRENT_BUILD_SIMULATOR ;
|
||||
|
||||
# deprecated use allocator=pool instead
|
||||
feature pool-allocators : on off debug : composite propagated link-incompatible ;
|
||||
feature.compose <pool-allocators>off : <define>TORRENT_DISABLE_POOL_ALLOCATOR ;
|
||||
|
|
|
@ -49,6 +49,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include <boost/asio/ip/address.hpp>
|
||||
|
||||
#if defined TORRENT_BUILD_SIMULATOR
|
||||
#include "simulator/simulator.hpp"
|
||||
#endif
|
||||
|
||||
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
||||
|
||||
#ifdef __OBJC__
|
||||
|
@ -57,12 +61,19 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
#if defined TORRENT_BUILD_SIMULATOR
|
||||
typedef sim::asio::ip::address address;
|
||||
typedef sim::asio::ip::address_v4 address_v4;
|
||||
#if TORRENT_USE_IPV6
|
||||
typedef sim::asio::ip::address_v6 address_v6;
|
||||
#endif
|
||||
#else
|
||||
typedef boost::asio::ip::address address;
|
||||
typedef boost::asio::ip::address_v4 address_v4;
|
||||
#if TORRENT_USE_IPV6
|
||||
typedef boost::asio::ip::address_v6 address_v6;
|
||||
#endif
|
||||
#endif // SIMULATOR
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -33,12 +33,25 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef TORRENT_DEADLINE_TIMER_HPP_INCLUDED
|
||||
#define TORRENT_DEADLINE_TIMER_HPP_INCLUDED
|
||||
|
||||
#include "libtorrent/config.hpp"
|
||||
|
||||
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
||||
|
||||
#include <boost/asio/high_resolution_timer.hpp>
|
||||
|
||||
#if defined TORRENT_BUILD_SIMULATOR
|
||||
#include "simulator/simulator.hpp"
|
||||
#endif
|
||||
|
||||
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
#if defined TORRENT_BUILD_SIMULATOR
|
||||
typedef sim::asio::high_resolution_timer deadline_timer;
|
||||
#else
|
||||
typedef boost::asio::high_resolution_timer deadline_timer;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // TORRENT_DEADLINE_TIMER_HPP_INCLUDED
|
||||
|
|
|
@ -48,6 +48,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include <boost/asio/io_service.hpp>
|
||||
|
||||
#if defined TORRENT_BUILD_SIMULATOR
|
||||
#include "simulator/simulator.hpp"
|
||||
#endif
|
||||
|
||||
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
||||
|
||||
#ifdef __OBJC__
|
||||
|
@ -56,7 +60,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
namespace libtorrent
|
||||
{
|
||||
#if defined TORRENT_BUILD_SIMULATOR
|
||||
typedef sim::asio::io_service io_service;
|
||||
#else
|
||||
typedef boost::asio::io_service io_service;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -47,13 +47,23 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#undef Protocol
|
||||
#endif
|
||||
|
||||
#if defined TORRENT_BUILD_SIMULATOR
|
||||
namespace sim { namespace asio {
|
||||
struct io_service;
|
||||
}}
|
||||
#endif
|
||||
|
||||
namespace boost { namespace asio {
|
||||
class io_service;
|
||||
}}
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
#if defined TORRENT_BUILD_SIMULATOR
|
||||
typedef sim::asio::io_service io_service;
|
||||
#else
|
||||
typedef boost::asio::io_service io_service;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -61,16 +61,28 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#undef Protocol
|
||||
#endif
|
||||
|
||||
#if defined TORRENT_BUILD_SIMULATOR
|
||||
#include "simulator/simulator.hpp"
|
||||
#endif
|
||||
|
||||
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
#if defined TORRENT_BUILD_SIMULATOR
|
||||
using sim::asio::ip::udp;
|
||||
using sim::asio::ip::tcp;
|
||||
using sim::asio::async_write;
|
||||
using sim::asio::async_read;
|
||||
using sim::asio::null_buffers;
|
||||
#else
|
||||
using boost::asio::ip::tcp;
|
||||
using boost::asio::ip::udp;
|
||||
using boost::asio::async_write;
|
||||
using boost::asio::async_read;
|
||||
using boost::asio::null_buffers;
|
||||
#endif
|
||||
|
||||
#if TORRENT_USE_IPV6
|
||||
#ifdef IPV6_V6ONLY
|
||||
|
|
|
@ -45,11 +45,17 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <boost/chrono.hpp>
|
||||
#endif
|
||||
|
||||
#if defined TORRENT_BUILD_SIMULATOR
|
||||
#include "simulator/simulator.hpp"
|
||||
#endif
|
||||
|
||||
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
||||
|
||||
namespace libtorrent {
|
||||
|
||||
#if defined BOOST_ASIO_HAS_STD_CHRONO
|
||||
#if defined TORRENT_BUILD_SIMULATOR
|
||||
typedef sim::chrono::high_resolution_clock clock_type;
|
||||
#elif defined BOOST_ASIO_HAS_STD_CHRONO
|
||||
typedef std::chrono::high_resolution_clock clock_type;
|
||||
#else
|
||||
typedef boost::chrono::high_resolution_clock clock_type;
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
import testing ;
|
||||
import feature : feature ;
|
||||
|
||||
use-project /torrent : .. ;
|
||||
use-project /libtorrent_test : ../test ;
|
||||
|
||||
use-project /libsimulator : libsimulator ;
|
||||
|
||||
project
|
||||
: requirements
|
||||
<simulator>on
|
||||
<library>/torrent//torrent
|
||||
<library>/libtorrent_test//libtorrent_test
|
||||
<source>swarm_suite.cpp
|
||||
<source>setup_swarm.cpp
|
||||
<source>setup_dht.cpp
|
||||
: default-build
|
||||
<threading>multi
|
||||
<invariant-checks>full
|
||||
<debug-iterators>on
|
||||
<picker-debugging>on
|
||||
;
|
||||
|
||||
test-suite libtorrent-sims :
|
||||
[ run test_swarm.cpp ]
|
||||
[ run test_utp.cpp ]
|
||||
[ run test_dht.cpp ]
|
||||
;
|
||||
|
|
@ -0,0 +1 @@
|
|||
Subproject commit b160ae7999a2eab64cb91c82b2ca6d7c222c6449
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2014-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 "libtorrent/session.hpp"
|
||||
#include "libtorrent/session_settings.hpp"
|
||||
#include "libtorrent/io_service.hpp"
|
||||
#include "libtorrent/deadline_timer.hpp"
|
||||
#include "libtorrent/address.hpp"
|
||||
#include "libtorrent/time.hpp"
|
||||
#include "libtorrent/settings_pack.hpp"
|
||||
#include "libtorrent/ip_filter.hpp"
|
||||
#include "libtorrent/alert_types.hpp"
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include "setup_dht.hpp"
|
||||
|
||||
namespace lt = libtorrent;
|
||||
using namespace sim;
|
||||
|
||||
namespace {
|
||||
|
||||
struct network
|
||||
{
|
||||
network(int num_nodes, network_setup_provider& config)
|
||||
: m_config(config)
|
||||
, m_ios(m_sim, asio::ip::address_v4::from_string("10.0.0.1"))
|
||||
, m_start_time(lt::clock_type::now())
|
||||
, m_timer(m_ios)
|
||||
, m_shutting_down(false)
|
||||
{
|
||||
|
||||
for (int i = 0; i < num_nodes; ++i)
|
||||
{
|
||||
// create a new io_service
|
||||
char ep[30];
|
||||
snprintf(ep, sizeof(ep), "50.0.%d.%d", (i + 1) >> 8, (i + 1) & 0xff);
|
||||
m_io_service.push_back(boost::make_shared<sim::asio::io_service>(
|
||||
boost::ref(m_sim), asio::ip::address_v4::from_string(ep)));
|
||||
|
||||
lt::settings_pack pack = m_config.add_session(i);
|
||||
|
||||
boost::shared_ptr<lt::session> ses = boost::make_shared<lt::session>(pack
|
||||
, boost::ref(*m_io_service.back()));
|
||||
m_nodes.push_back(ses);
|
||||
|
||||
m_config.setup_session(*ses, i);
|
||||
|
||||
ses->set_alert_notify(boost::bind(&network::on_alert_notify, this, i));
|
||||
}
|
||||
|
||||
m_timer.expires_from_now(lt::seconds(1));
|
||||
m_timer.async_wait(boost::bind(&network::on_tick, this, _1));
|
||||
|
||||
sim::dump_network_graph(m_sim, "../dht-sim.dot");
|
||||
}
|
||||
|
||||
void on_tick(lt::error_code const& ec)
|
||||
{
|
||||
if (ec || m_shutting_down) return;
|
||||
|
||||
if (m_config.on_tick())
|
||||
{
|
||||
terminate();
|
||||
return;
|
||||
}
|
||||
|
||||
m_timer.expires_from_now(lt::seconds(1));
|
||||
m_timer.async_wait(boost::bind(&network::on_tick, this, _1));
|
||||
}
|
||||
|
||||
void on_alert_notify(int session_index)
|
||||
{
|
||||
// this function is called inside libtorrent and we cannot perform work
|
||||
// immediately in it. We have to notify the outside to pull all the alerts
|
||||
m_io_service[session_index]->post(boost::bind(&network::on_alerts, this, session_index));
|
||||
}
|
||||
|
||||
void on_alerts(int session_index)
|
||||
{
|
||||
std::vector<lt::alert*> alerts;
|
||||
|
||||
lt::session* ses = m_nodes[session_index].get();
|
||||
|
||||
// when shutting down, we may have destructed the session
|
||||
if (ses == NULL) return;
|
||||
|
||||
bool term = false;
|
||||
ses->pop_alerts(&alerts);
|
||||
|
||||
for (std::vector<lt::alert*>::iterator i = alerts.begin();
|
||||
i != alerts.end(); ++i)
|
||||
{
|
||||
lt::alert* a = *i;
|
||||
|
||||
if (session_index == 0)
|
||||
{
|
||||
// only log the experience of node 0
|
||||
lt::time_duration d = a->timestamp() - m_start_time;
|
||||
boost::uint32_t millis = lt::duration_cast<lt::milliseconds>(d).count();
|
||||
printf("%4d.%03d: [%02d] %s\n", millis / 1000, millis % 1000,
|
||||
session_index, a->message().c_str());
|
||||
}
|
||||
|
||||
if (m_config.on_alert(a, session_index))
|
||||
term = true;
|
||||
|
||||
if (lt::alert_cast<lt::listen_succeeded_alert>(a))
|
||||
{
|
||||
// add a single DHT node to bootstrap from. Make everyone bootstrap
|
||||
// from the node added 3 steps earlier (this makes the distribution a
|
||||
// bit unrealisticly uniform).
|
||||
int dht_bootstrap = (std::max)(0, session_index - 3);
|
||||
|
||||
char ep[50];
|
||||
snprintf(ep, sizeof(ep), "50.0.%d.%d", (dht_bootstrap + 1) >> 8, (dht_bootstrap + 1) & 0xff);
|
||||
ses->add_dht_node(std::pair<std::string, int>(
|
||||
ep, m_nodes[dht_bootstrap]->listen_port()));
|
||||
}
|
||||
}
|
||||
|
||||
if (term) terminate();
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
m_sim.run();
|
||||
printf("simulation::run() returned\n");
|
||||
}
|
||||
|
||||
void terminate()
|
||||
{
|
||||
printf("TERMINATING\n");
|
||||
|
||||
m_config.on_exit();
|
||||
|
||||
// terminate simulation
|
||||
for (int i = 0; i < int(m_nodes.size()); ++i)
|
||||
{
|
||||
m_zombies.push_back(m_nodes[i]->abort());
|
||||
m_nodes[i].reset();
|
||||
}
|
||||
|
||||
m_shutting_down = true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
network_setup_provider& m_config;
|
||||
|
||||
sim::simulation m_sim;
|
||||
asio::io_service m_ios;
|
||||
lt::time_point m_start_time;
|
||||
|
||||
std::vector<boost::shared_ptr<lt::session> > m_nodes;
|
||||
std::vector<boost::shared_ptr<sim::asio::io_service> > m_io_service;
|
||||
std::vector<lt::session_proxy> m_zombies;
|
||||
lt::deadline_timer m_timer;
|
||||
bool m_shutting_down;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void setup_dht(int num_nodes, network_setup_provider& cfg)
|
||||
{
|
||||
network s(num_nodes, cfg);
|
||||
s.run();
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
|
||||
/*
|
||||
|
||||
Copyright (c) 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 "libtorrent/io_service.hpp"
|
||||
|
||||
namespace libtorrent {
|
||||
class alert;
|
||||
struct settings_pack;
|
||||
struct add_torrent_params;
|
||||
class session;
|
||||
}
|
||||
|
||||
struct network_setup_provider
|
||||
{
|
||||
// can be used to check expected end conditions
|
||||
virtual void on_exit() {}
|
||||
|
||||
// called for every alert. if the simulation is done, return true
|
||||
virtual bool on_alert(libtorrent::alert const* alert, int session_idx)
|
||||
{ return false; }
|
||||
|
||||
virtual bool on_tick() = 0;
|
||||
|
||||
// called for every session that's added
|
||||
virtual libtorrent::settings_pack add_session(int idx) = 0;
|
||||
|
||||
// called for a session right after it has been created
|
||||
virtual void setup_session(libtorrent::session& ses, int idx) = 0;
|
||||
};
|
||||
|
||||
void setup_dht(int num_nodes, network_setup_provider& config);
|
||||
|
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2014-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 "libtorrent/session.hpp"
|
||||
#include "libtorrent/session_settings.hpp"
|
||||
#include "libtorrent/io_service.hpp"
|
||||
#include "libtorrent/deadline_timer.hpp"
|
||||
#include "libtorrent/address.hpp"
|
||||
#include "libtorrent/add_torrent_params.hpp"
|
||||
#include "libtorrent/time.hpp"
|
||||
#include "libtorrent/settings_pack.hpp"
|
||||
#include "libtorrent/ip_filter.hpp"
|
||||
#include "libtorrent/alert_types.hpp"
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include "setup_swarm.hpp"
|
||||
|
||||
namespace lt = libtorrent;
|
||||
using namespace sim;
|
||||
|
||||
namespace {
|
||||
|
||||
struct swarm
|
||||
{
|
||||
swarm(int num_nodes, swarm_setup_provider& config)
|
||||
: m_config(config)
|
||||
, m_ios(m_sim, asio::ip::address_v4::from_string("0.0.0.0"))
|
||||
, m_start_time(lt::clock_type::now())
|
||||
, m_timer(m_ios)
|
||||
, m_shutting_down(false)
|
||||
, m_tick(0)
|
||||
{
|
||||
|
||||
for (int i = 0; i < num_nodes; ++i)
|
||||
{
|
||||
// create a new io_service
|
||||
char ep[30];
|
||||
snprintf(ep, sizeof(ep), "50.0.%d.%d", (i + 1) >> 8, (i + 1) & 0xff);
|
||||
m_io_service.push_back(boost::make_shared<sim::asio::io_service>(
|
||||
boost::ref(m_sim), asio::ip::address_v4::from_string(ep)));
|
||||
|
||||
lt::settings_pack pack = m_config.add_session(i);
|
||||
|
||||
boost::shared_ptr<lt::session> ses =
|
||||
boost::make_shared<lt::session>(pack
|
||||
, boost::ref(*m_io_service.back()));
|
||||
m_nodes.push_back(ses);
|
||||
|
||||
// reserve a slot in here for when the torrent gets added (notified by
|
||||
// an alert)
|
||||
m_torrents.push_back(lt::torrent_handle());
|
||||
|
||||
lt::add_torrent_params params = m_config.add_torrent(i);
|
||||
ses->async_add_torrent(params);
|
||||
|
||||
ses->set_alert_notify(boost::bind(&swarm::on_alert_notify, this, i));
|
||||
}
|
||||
|
||||
m_timer.expires_from_now(lt::seconds(1));
|
||||
m_timer.async_wait(boost::bind(&swarm::on_tick, this, _1));
|
||||
}
|
||||
|
||||
void on_tick(lt::error_code const& ec)
|
||||
{
|
||||
if (ec || m_shutting_down) return;
|
||||
|
||||
lt::time_duration d = lt::clock_type::now() - m_start_time;
|
||||
boost::uint32_t millis = lt::duration_cast<lt::milliseconds>(d).count();
|
||||
printf("%4d.%03d: TICK %d\n", millis / 1000, millis % 1000, m_tick);
|
||||
|
||||
++m_tick;
|
||||
|
||||
if (m_tick > 120)
|
||||
{
|
||||
terminate();
|
||||
return;
|
||||
}
|
||||
|
||||
m_timer.expires_from_now(lt::seconds(1));
|
||||
m_timer.async_wait(boost::bind(&swarm::on_tick, this, _1));
|
||||
}
|
||||
|
||||
void on_alert_notify(int session_index)
|
||||
{
|
||||
// this function is called inside libtorrent and we cannot perform work
|
||||
// immediately in it. We have to notify the outside to pull all the alerts
|
||||
m_io_service[session_index]->post(boost::bind(&swarm::on_alerts, this, session_index));
|
||||
}
|
||||
|
||||
void on_alerts(int session_index)
|
||||
{
|
||||
std::vector<lt::alert*> alerts;
|
||||
|
||||
lt::session* ses = m_nodes[session_index].get();
|
||||
|
||||
// when shutting down, we may have destructed the session
|
||||
if (ses == NULL) return;
|
||||
|
||||
bool term = false;
|
||||
ses->pop_alerts(&alerts);
|
||||
|
||||
for (std::vector<lt::alert*>::iterator i = alerts.begin();
|
||||
i != alerts.end(); ++i)
|
||||
{
|
||||
lt::alert* a = *i;
|
||||
|
||||
lt::time_duration d = a->timestamp() - m_start_time;
|
||||
boost::uint32_t millis = lt::duration_cast<lt::milliseconds>(d).count();
|
||||
printf("%4d.%03d: [%02d] %s\n", millis / 1000, millis % 1000,
|
||||
session_index, a->message().c_str());
|
||||
|
||||
// if a torrent was added save the torrent handle
|
||||
if (lt::add_torrent_alert* at = lt::alert_cast<lt::add_torrent_alert>(a))
|
||||
{
|
||||
lt::torrent_handle h = at->handle;
|
||||
m_torrents[session_index] = h;
|
||||
|
||||
// now, connect this torrent to all the others in the swarm
|
||||
for (int k = 0; k < session_index; ++k)
|
||||
{
|
||||
char ep[30];
|
||||
snprintf(ep, sizeof(ep), "50.0.%d.%d", (k + 1) >> 8, (k + 1) & 0xff);
|
||||
h.connect_peer(lt::tcp::endpoint(
|
||||
lt::address_v4::from_string(ep), 6881));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_config.on_alert(a, session_index, m_torrents))
|
||||
term = true;
|
||||
}
|
||||
|
||||
if (term) terminate();
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
m_sim.run();
|
||||
printf("simulation::run() returned\n");
|
||||
}
|
||||
|
||||
void terminate()
|
||||
{
|
||||
printf("TERMINATING\n");
|
||||
|
||||
m_config.on_exit(m_torrents);
|
||||
|
||||
// terminate simulation
|
||||
for (int i = 0; i < int(m_nodes.size()); ++i)
|
||||
{
|
||||
m_zombies.push_back(m_nodes[i]->abort());
|
||||
m_nodes[i].reset();
|
||||
}
|
||||
|
||||
m_shutting_down = true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
swarm_setup_provider& m_config;
|
||||
|
||||
sim::simulation m_sim;
|
||||
asio::io_service m_ios;
|
||||
lt::time_point m_start_time;
|
||||
|
||||
std::vector<boost::shared_ptr<lt::session> > m_nodes;
|
||||
std::vector<boost::shared_ptr<sim::asio::io_service> > m_io_service;
|
||||
std::vector<lt::torrent_handle> m_torrents;
|
||||
std::vector<lt::session_proxy> m_zombies;
|
||||
lt::deadline_timer m_timer;
|
||||
bool m_shutting_down;
|
||||
int m_tick;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void setup_swarm(int num_nodes, swarm_setup_provider& cfg)
|
||||
{
|
||||
swarm s(num_nodes, cfg);
|
||||
s.run();
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 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 "libtorrent/io_service.hpp"
|
||||
#include "libtorrent/settings_pack.hpp"
|
||||
#include "libtorrent/add_torrent_params.hpp"
|
||||
|
||||
struct swarm_setup_provider
|
||||
{
|
||||
// can be used to check expected end conditions
|
||||
virtual void on_exit(std::vector<libtorrent::torrent_handle> const& torrents) {}
|
||||
|
||||
// called for every alert. if the simulation is done, return true
|
||||
virtual bool on_alert(libtorrent::alert const* alert
|
||||
, int session_idx
|
||||
, std::vector<libtorrent::torrent_handle> const& handles) { return false; }
|
||||
|
||||
// called for every torrent that's added (and every session that's started).
|
||||
// this is useful to give every session a unique save path and to make some
|
||||
// sessions seeds and others downloaders
|
||||
virtual libtorrent::add_torrent_params add_torrent(int idx) = 0;
|
||||
|
||||
// called for every session that's added
|
||||
virtual libtorrent::settings_pack add_session(int idx) = 0;
|
||||
};
|
||||
|
||||
void setup_swarm(int num_nodes, swarm_setup_provider& config);
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2014, 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/settings_pack.hpp"
|
||||
#include "libtorrent/alert_types.hpp"
|
||||
#include "libtorrent/time.hpp" // for clock_type
|
||||
#include <fstream>
|
||||
|
||||
#include "test.hpp"
|
||||
#include "setup_transfer.hpp" // for create_torrent (factor this out!)
|
||||
#include "setup_swarm.hpp"
|
||||
#include "swarm_suite.hpp"
|
||||
#include "settings.hpp"
|
||||
|
||||
using namespace libtorrent;
|
||||
namespace lt = libtorrent;
|
||||
|
||||
struct swarm_config : swarm_setup_provider
|
||||
{
|
||||
swarm_config(int flags)
|
||||
: m_flags(flags)
|
||||
, m_swarm_id(std::rand())
|
||||
, m_start_time(lt::clock_type::now())
|
||||
{
|
||||
// in case the previous run was terminated
|
||||
error_code ec;
|
||||
char save_path[200];
|
||||
snprintf(save_path, sizeof(save_path), "swarm-%04d-peer-%02d"
|
||||
, m_swarm_id, 0);
|
||||
create_directory(save_path, ec);
|
||||
std::ofstream file(combine_path(save_path, "temporary").c_str());
|
||||
m_ti = ::create_torrent(&file, 0x4000, 9, false);
|
||||
file.close();
|
||||
}
|
||||
|
||||
virtual void on_exit(std::vector<torrent_handle> const& torrents)
|
||||
{
|
||||
TEST_CHECK(torrents.size() > 0);
|
||||
for (int i = 0; i < int(torrents.size()); ++i)
|
||||
{
|
||||
torrent_status st = torrents[i].status();
|
||||
TEST_CHECK(st.is_seeding);
|
||||
TEST_CHECK(st.total_upload > 0 || st.total_download > 0);
|
||||
}
|
||||
|
||||
TEST_CHECK(lt::clock_type::now() < m_start_time + lt::milliseconds(2100));
|
||||
}
|
||||
|
||||
// called for every alert. if the simulation is done, return true
|
||||
virtual bool on_alert(libtorrent::alert const* alert
|
||||
, int session_idx
|
||||
, std::vector<libtorrent::torrent_handle> const& torrents)
|
||||
{
|
||||
if (torrents.empty()) return false;
|
||||
|
||||
bool all_are_seeding = true;
|
||||
for (int i = 0; i < int(torrents.size()); ++i)
|
||||
{
|
||||
if (torrents[i].status().is_seeding)
|
||||
continue;
|
||||
|
||||
all_are_seeding = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// if all torrents are seeds, terminate the simulation, we're done
|
||||
return all_are_seeding;
|
||||
}
|
||||
|
||||
// called for every torrent that's added (and every session that's started).
|
||||
// this is useful to give every session a unique save path and to make some
|
||||
// sessions seeds and others downloaders
|
||||
virtual libtorrent::add_torrent_params add_torrent(int idx)
|
||||
{
|
||||
add_torrent_params p;
|
||||
p.flags &= ~add_torrent_params::flag_paused;
|
||||
p.flags &= ~add_torrent_params::flag_auto_managed;
|
||||
|
||||
p.ti = m_ti;
|
||||
|
||||
// only the first session is set to seed mode
|
||||
if (idx == 0)
|
||||
{
|
||||
if (m_flags & seed_mode) p.flags |= add_torrent_params::flag_seed_mode;
|
||||
}
|
||||
|
||||
char save_path[200];
|
||||
snprintf(save_path, sizeof(save_path), "swarm-%04d-peer-%02d"
|
||||
, m_swarm_id, idx);
|
||||
p.save_path = save_path;
|
||||
return p;
|
||||
}
|
||||
|
||||
// called for every session that's added
|
||||
virtual libtorrent::settings_pack add_session(int idx)
|
||||
{
|
||||
settings_pack pack = settings();
|
||||
|
||||
pack.set_bool(settings_pack::strict_super_seeding, m_flags & strict_super_seeding);
|
||||
|
||||
if (m_flags & suggest_read_cache)
|
||||
pack.set_int(settings_pack::suggest_mode, settings_pack::suggest_read_cache);
|
||||
else
|
||||
pack.set_int(settings_pack::suggest_mode, 0);
|
||||
|
||||
if (m_flags & explicit_cache)
|
||||
{
|
||||
pack.set_bool(settings_pack::explicit_read_cache, true);
|
||||
pack.set_int(settings_pack::explicit_cache_interval, 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
pack.set_bool(settings_pack::explicit_read_cache, false);
|
||||
}
|
||||
|
||||
if (m_flags & utp_only)
|
||||
{
|
||||
pack.set_bool(settings_pack::enable_incoming_utp, true);
|
||||
pack.set_bool(settings_pack::enable_outgoing_utp, true);
|
||||
pack.set_bool(settings_pack::enable_incoming_tcp, false);
|
||||
pack.set_bool(settings_pack::enable_outgoing_tcp, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
pack.set_bool(settings_pack::enable_incoming_utp, false);
|
||||
pack.set_bool(settings_pack::enable_outgoing_utp, false);
|
||||
pack.set_bool(settings_pack::enable_incoming_tcp, true);
|
||||
pack.set_bool(settings_pack::enable_outgoing_tcp, true);
|
||||
}
|
||||
|
||||
// make sure the sessions have different peer ids
|
||||
lt::peer_id pid;
|
||||
std::generate(&pid[0], &pid[0] + 20, &random_byte);
|
||||
pack.set_str(lt::settings_pack::peer_fingerprint, pid.to_string());
|
||||
|
||||
return pack;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_flags;
|
||||
int m_swarm_id;
|
||||
lt::time_point m_start_time;
|
||||
boost::shared_ptr<libtorrent::torrent_info> m_ti;
|
||||
};
|
||||
|
||||
void simulate_swarm(int flags)
|
||||
{
|
||||
fprintf(stderr, "\n\n ==== TEST SWARM === %s%s%s%s%s%s%s ===\n\n\n"
|
||||
, (flags & super_seeding) ? "super-seeding ": ""
|
||||
, (flags & strict_super_seeding) ? "strict-super-seeding ": ""
|
||||
, (flags & seed_mode) ? "seed-mode ": ""
|
||||
, (flags & time_critical) ? "time-critical ": ""
|
||||
, (flags & suggest_read_cache) ? "suggest-read-cache ": ""
|
||||
, (flags & explicit_cache) ? "explicit-cache ": ""
|
||||
, (flags & utp_only) ? "utp-only": ""
|
||||
);
|
||||
|
||||
swarm_config cfg(flags);
|
||||
setup_swarm(2, cfg);
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2014, 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 "test.hpp"
|
||||
|
||||
enum test_flags_t
|
||||
{
|
||||
super_seeding = 1,
|
||||
strict_super_seeding = 2,
|
||||
seed_mode = 4,
|
||||
time_critical = 8,
|
||||
suggest_read_cache = 16,
|
||||
explicit_cache = 32,
|
||||
utp_only = 64
|
||||
};
|
||||
|
||||
void EXPORT simulate_swarm(int flags = 0);
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 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 "test.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "setup_dht.hpp"
|
||||
#include "libtorrent/alert_types.hpp"
|
||||
#include "libtorrent/alert.hpp"
|
||||
#include "libtorrent/time.hpp"
|
||||
#include "libtorrent/settings_pack.hpp"
|
||||
#include "libtorrent/session_settings.hpp"
|
||||
#include "libtorrent/session.hpp"
|
||||
#include "libtorrent/alert_types.hpp"
|
||||
|
||||
namespace lt = libtorrent;
|
||||
|
||||
struct network_config : network_setup_provider
|
||||
{
|
||||
network_config()
|
||||
: m_start_time(lt::clock_type::now())
|
||||
{}
|
||||
|
||||
virtual void on_exit() override final {}
|
||||
|
||||
// called for every alert. if the simulation is done, return true
|
||||
virtual bool on_alert(lt::alert const* alert
|
||||
, int session_idx) override final
|
||||
{
|
||||
if (lt::dht_stats_alert const* p = lt::alert_cast<lt::dht_stats_alert>(alert))
|
||||
{
|
||||
int bucket = 0;
|
||||
for (std::vector<lt::dht_routing_bucket>::const_iterator i = p->routing_table.begin()
|
||||
, end(p->routing_table.end()); i != end; ++i, ++bucket)
|
||||
{
|
||||
char const* progress_bar =
|
||||
"################################"
|
||||
"################################"
|
||||
"################################"
|
||||
"################################";
|
||||
char const* short_progress_bar = "--------";
|
||||
printf("%3d [%3d, %d] %s%s\n"
|
||||
, bucket, i->num_nodes, i->num_replacements
|
||||
, progress_bar + (128 - i->num_nodes)
|
||||
, short_progress_bar + (8 - (std::min)(8, i->num_replacements)));
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool on_tick() override final
|
||||
{
|
||||
m_first_session->post_dht_stats();
|
||||
if (++m_ticks > 80) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// called for every session that's added
|
||||
virtual lt::settings_pack add_session(int idx) override final
|
||||
{
|
||||
lt::settings_pack pack = settings();
|
||||
|
||||
pack.set_bool(lt::settings_pack::enable_dht, true);
|
||||
|
||||
return pack;
|
||||
}
|
||||
|
||||
virtual void setup_session(lt::session& ses, int idx) override final
|
||||
{
|
||||
if (idx == 0) m_first_session = &ses;
|
||||
|
||||
// we have to do this since all of our simulated IP addresses are close to
|
||||
// each other
|
||||
lt::dht_settings sett;
|
||||
sett.restrict_routing_ips = false;
|
||||
sett.restrict_search_ips = false;
|
||||
sett.privacy_lookups = false;
|
||||
sett.extended_routing_table = false;
|
||||
ses.set_dht_settings(sett);
|
||||
}
|
||||
|
||||
private:
|
||||
lt::time_point m_start_time;
|
||||
boost::shared_ptr<lt::torrent_info> m_ti;
|
||||
lt::session* m_first_session;
|
||||
int m_ticks;
|
||||
};
|
||||
|
||||
TORRENT_TEST(dht)
|
||||
{
|
||||
network_config cfg;
|
||||
setup_dht(50, cfg);
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2008, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "swarm_suite.hpp"
|
||||
#include "test.hpp"
|
||||
|
||||
TORRENT_TEST(seed_mode)
|
||||
{
|
||||
// with seed mode
|
||||
simulate_swarm(seed_mode);
|
||||
}
|
||||
|
||||
TORRENT_TEST(plain)
|
||||
{
|
||||
simulate_swarm();
|
||||
}
|
||||
|
||||
TORRENT_TEST(suggest)
|
||||
{
|
||||
// with suggest pieces
|
||||
simulate_swarm(suggest_read_cache);
|
||||
}
|
||||
|
||||
TORRENT_TEST(utp)
|
||||
{
|
||||
simulate_swarm(utp_only);
|
||||
}
|
||||
TORRENT_TEST(explicit_cache)
|
||||
{
|
||||
// test explicit cache
|
||||
simulate_swarm(suggest_read_cache | explicit_cache);
|
||||
}
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2008, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "libtorrent/session.hpp"
|
||||
#include "libtorrent/settings_pack.hpp"
|
||||
#include "libtorrent/alert_types.hpp"
|
||||
#include "libtorrent/time.hpp" // for clock_type
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include "test.hpp"
|
||||
#include "setup_swarm.hpp"
|
||||
#include "setup_transfer.hpp" // for create_torrent (factor this out!)
|
||||
#include "settings.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace libtorrent;
|
||||
namespace lt = libtorrent;
|
||||
|
||||
// TODO: a lot of this class is boiler plate. Factor out into a reusable unit
|
||||
struct swarm_config : swarm_setup_provider
|
||||
{
|
||||
swarm_config(int num_peers)
|
||||
: m_swarm_id(std::rand())
|
||||
, m_start_time(lt::clock_type::now())
|
||||
{
|
||||
// in case the previous run did not exit gracefully
|
||||
clear_download_directories(num_peers);
|
||||
|
||||
error_code ec;
|
||||
char save_path[200];
|
||||
snprintf(save_path, sizeof(save_path), "swarm-%04d-peer-%02d"
|
||||
, m_swarm_id, 0);
|
||||
|
||||
create_directory(save_path, ec);
|
||||
std::ofstream file(combine_path(save_path, "temporary").c_str());
|
||||
m_ti = ::create_torrent(&file, 0x4000, 90, false);
|
||||
file.close();
|
||||
}
|
||||
|
||||
virtual void on_exit(std::vector<torrent_handle> const& torrents)
|
||||
{
|
||||
TEST_CHECK(torrents.size() > 0);
|
||||
for (int i = 0; i < int(torrents.size()); ++i)
|
||||
{
|
||||
torrent_status st = torrents[i].status();
|
||||
TEST_CHECK(st.is_seeding);
|
||||
TEST_CHECK(st.total_upload > 0 || st.total_download > 0);
|
||||
}
|
||||
|
||||
// if this check fails, there is a performance regression in the protocol,
|
||||
// either uTP or bittorrent itself. Be careful with the download request
|
||||
// queue size (and make sure it can grow fast enough, to keep up with
|
||||
// slow-start) and the send buffer watermark
|
||||
TEST_CHECK(lt::clock_type::now() < m_start_time + lt::milliseconds(8500));
|
||||
|
||||
// clean up the download directories to make the next run start from
|
||||
// scratch.
|
||||
clear_download_directories(int(torrents.size()));
|
||||
}
|
||||
|
||||
void clear_download_directories(int num_peers)
|
||||
{
|
||||
for (int i = 0; i < num_peers; ++i)
|
||||
{
|
||||
error_code ec;
|
||||
char save_path[200];
|
||||
snprintf(save_path, sizeof(save_path), "swarm-%04d-peer-%02d"
|
||||
, m_swarm_id, i);
|
||||
|
||||
// in case the previous run did not exit gracefully
|
||||
remove_all(save_path, ec);
|
||||
}
|
||||
}
|
||||
|
||||
// called for every alert. if the simulation is done, return true
|
||||
virtual bool on_alert(libtorrent::alert const* alert
|
||||
, int session_idx
|
||||
, std::vector<libtorrent::torrent_handle> const& torrents)
|
||||
{
|
||||
if (torrents.empty()) return false;
|
||||
|
||||
bool all_are_seeding = true;
|
||||
for (int i = 0; i < int(torrents.size()); ++i)
|
||||
{
|
||||
if (torrents[i].status().is_seeding)
|
||||
continue;
|
||||
|
||||
all_are_seeding = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// if all torrents are seeds, terminate the simulation, we're done
|
||||
return all_are_seeding;
|
||||
}
|
||||
|
||||
// called for every torrent that's added (and every session that's started).
|
||||
// this is useful to give every session a unique save path and to make some
|
||||
// sessions seeds and others downloaders
|
||||
virtual libtorrent::add_torrent_params add_torrent(int idx)
|
||||
{
|
||||
add_torrent_params p;
|
||||
p.flags &= ~add_torrent_params::flag_paused;
|
||||
p.flags &= ~add_torrent_params::flag_auto_managed;
|
||||
|
||||
if (idx == 0)
|
||||
{
|
||||
// skip checking up front, and get started with the transfer sooner
|
||||
p.flags |= add_torrent_params::flag_seed_mode;
|
||||
}
|
||||
|
||||
p.ti = m_ti;
|
||||
|
||||
char save_path[200];
|
||||
snprintf(save_path, sizeof(save_path), "swarm-%04d-peer-%02d"
|
||||
, m_swarm_id, idx);
|
||||
p.save_path = save_path;
|
||||
return p;
|
||||
}
|
||||
|
||||
// called for every session that's added
|
||||
virtual libtorrent::settings_pack add_session(int idx)
|
||||
{
|
||||
settings_pack pack = settings();
|
||||
|
||||
// force uTP connection
|
||||
pack.set_bool(settings_pack::enable_incoming_utp, true);
|
||||
pack.set_bool(settings_pack::enable_outgoing_utp, true);
|
||||
pack.set_bool(settings_pack::enable_incoming_tcp, false);
|
||||
pack.set_bool(settings_pack::enable_outgoing_tcp, false);
|
||||
|
||||
// the encryption handshake adds several round-trips to the bittorrent
|
||||
// handshake, and slows it down significantly
|
||||
pack.set_int(settings_pack::out_enc_policy, settings_pack::pe_disabled);
|
||||
pack.set_int(settings_pack::in_enc_policy, settings_pack::pe_disabled);
|
||||
|
||||
// make sure the sessions have different peer ids
|
||||
lt::peer_id pid;
|
||||
std::generate(&pid[0], &pid[0] + 20, &random_byte);
|
||||
pack.set_str(lt::settings_pack::peer_fingerprint, pid.to_string());
|
||||
|
||||
return pack;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_swarm_id;
|
||||
lt::time_point m_start_time;
|
||||
boost::shared_ptr<libtorrent::torrent_info> m_ti;
|
||||
};
|
||||
|
||||
TORRENT_TEST(utp)
|
||||
{
|
||||
// TODO: 3 simulate packet loss
|
||||
// TODO: 3 simulate unpredictible latencies
|
||||
// TODO: 3 simulate proper (taildrop) queues (perhaps even RED and BLUE)
|
||||
swarm_config cfg(2);
|
||||
setup_swarm(2, cfg);
|
||||
}
|
||||
|
|
@ -5618,7 +5618,7 @@ retry:
|
|||
session_impl::~session_impl()
|
||||
{
|
||||
// this is not allowed to be the network thread!
|
||||
TORRENT_ASSERT(is_not_thread());
|
||||
// TORRENT_ASSERT(is_not_thread());
|
||||
|
||||
#if defined TORRENT_ASIO_DEBUGGING
|
||||
int counter = 0;
|
||||
|
|
|
@ -59,6 +59,7 @@ lib libtorrent_test
|
|||
web_seed_suite.cpp
|
||||
swarm_suite.cpp
|
||||
test_utils.cpp
|
||||
settings.cpp
|
||||
|
||||
: # requirements
|
||||
# this is used to determine whether
|
||||
|
@ -76,6 +77,7 @@ lib libtorrent_test
|
|||
: # user-requirements
|
||||
<link>shared:<define>TORRENT_LINK_TEST_SHARED
|
||||
<logging>on
|
||||
<include>.
|
||||
;
|
||||
|
||||
explicit libtorrent_test ;
|
||||
|
|
|
@ -100,7 +100,7 @@ EXTRA_PROGRAMS = $(test_programs)
|
|||
|
||||
noinst_HEADERS = test.hpp setup_transfer.hpp dht_server.hpp \
|
||||
peer_server.hpp udp_tracker.hpp web_seed_suite.hpp swarm_suite.hpp \
|
||||
test_utils.hpp
|
||||
test_utils.hpp settings.hpp
|
||||
|
||||
libtest_la_SOURCES = main.cpp \
|
||||
test.cpp \
|
||||
|
@ -110,7 +110,8 @@ libtest_la_SOURCES = main.cpp \
|
|||
peer_server.cpp \
|
||||
web_seed_suite.cpp \
|
||||
swarm_suite.cpp \
|
||||
test_utils.cpp
|
||||
test_utils.cpp \
|
||||
settings.cpp \
|
||||
|
||||
test_primitives_SOURCES = \
|
||||
test_primitives.cpp \
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 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 "libtorrent/settings_pack.hpp"
|
||||
#include "libtorrent/alert.hpp"
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
libtorrent::settings_pack settings()
|
||||
{
|
||||
const int mask = alert::all_categories
|
||||
& ~(alert::progress_notification
|
||||
| alert::performance_warning
|
||||
| alert::stats_notification);
|
||||
|
||||
settings_pack pack;
|
||||
pack.set_bool(settings_pack::enable_lsd, false);
|
||||
pack.set_bool(settings_pack::enable_natpmp, false);
|
||||
pack.set_bool(settings_pack::enable_upnp, false);
|
||||
pack.set_bool(settings_pack::enable_dht, false);
|
||||
|
||||
pack.set_int(settings_pack::alert_mask, mask);
|
||||
|
||||
#ifndef TORRENT_BUILD_SIMULATOR
|
||||
pack.set_bool(settings_pack::allow_multiple_connections_per_ip, true);
|
||||
#else
|
||||
// we use 0 threads (disk I/O operations will be performed in the network
|
||||
// thread) to be simulator friendly.
|
||||
pack.set_int(settings_pack::aio_threads, 0);
|
||||
#endif
|
||||
|
||||
return pack;
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 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 "libtorrent/settings_pack.hpp"
|
||||
|
||||
libtorrent::settings_pack settings();
|
||||
|
Loading…
Reference in New Issue