initial support for ut_metadata
This commit is contained in:
parent
db0ae6bd7e
commit
f3d45fcfc1
1
Jamfile
1
Jamfile
|
@ -236,6 +236,7 @@ SOURCES =
|
|||
metadata_transfer
|
||||
upnp
|
||||
ut_pex
|
||||
ut_metadata
|
||||
logger
|
||||
file_pool
|
||||
lsd
|
||||
|
|
|
@ -267,6 +267,8 @@ namespace libtorrent
|
|||
// initializes m_RC4_handler
|
||||
void init_pe_RC4_handler(char const* secret, sha1_hash const& stream_key);
|
||||
|
||||
public:
|
||||
|
||||
// these functions encrypt the send buffer if m_rc4_encrypted
|
||||
// is true, otherwise it passes the call to the
|
||||
// peer_connection functions of the same names
|
||||
|
@ -283,6 +285,8 @@ namespace libtorrent
|
|||
}
|
||||
void setup_send();
|
||||
|
||||
private:
|
||||
|
||||
// Returns offset at which bytestream (src, src + src_size)
|
||||
// matches bytestream(target, target + target_size).
|
||||
// If no sync found, return -1
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2007, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TORRENT_UT_METADATA_HPP_INCLUDED
|
||||
#define TORRENT_UT_METADATA_HPP_INCLUDED
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 1)
|
||||
#endif
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include "libtorrent/config.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
struct torrent_plugin;
|
||||
class torrent;
|
||||
TORRENT_EXPORT boost::shared_ptr<torrent_plugin> create_ut_metadata_plugin(torrent*, void*);
|
||||
}
|
||||
|
||||
#endif // TORRENT_UT_METADATA_HPP_INCLUDED
|
||||
|
|
@ -399,6 +399,11 @@ namespace libtorrent
|
|||
int send_buffer_capacity() const
|
||||
{ return m_send_buffer.capacity(); }
|
||||
|
||||
int packet_size() const { return m_packet_size; }
|
||||
|
||||
bool packet_finished() const
|
||||
{ return m_packet_size <= m_recv_pos; }
|
||||
|
||||
protected:
|
||||
|
||||
virtual void get_specific_peer_info(peer_info& p) const = 0;
|
||||
|
@ -443,12 +448,6 @@ namespace libtorrent
|
|||
void cut_receive_buffer(int size, int packet_size);
|
||||
|
||||
void reset_recv_buffer(int packet_size);
|
||||
int packet_size() const { return m_packet_size; }
|
||||
|
||||
bool packet_finished() const
|
||||
{
|
||||
return m_packet_size <= m_recv_pos;
|
||||
}
|
||||
|
||||
void setup_receive();
|
||||
|
||||
|
|
|
@ -0,0 +1,448 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2007, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "libtorrent/pch.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 1)
|
||||
#endif
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <numeric>
|
||||
#include <cstdio>
|
||||
|
||||
#include "libtorrent/peer_connection.hpp"
|
||||
#include "libtorrent/bt_peer_connection.hpp"
|
||||
#include "libtorrent/hasher.hpp"
|
||||
#include "libtorrent/bencode.hpp"
|
||||
#include "libtorrent/torrent.hpp"
|
||||
#include "libtorrent/extensions.hpp"
|
||||
#include "libtorrent/extensions/metadata_transfer.hpp"
|
||||
#include "libtorrent/alert_types.hpp"
|
||||
|
||||
namespace libtorrent { namespace
|
||||
{
|
||||
int div_round_up(int numerator, int denominator)
|
||||
{
|
||||
return (numerator + denominator - 1) / denominator;
|
||||
}
|
||||
|
||||
void nop(char*) {}
|
||||
|
||||
struct ut_metadata_plugin : torrent_plugin
|
||||
{
|
||||
ut_metadata_plugin(torrent& t)
|
||||
: m_torrent(t)
|
||||
, m_metadata_progress(0)
|
||||
, m_metadata_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void on_files_checked()
|
||||
{
|
||||
// if the torrent is a seed, copy the metadata from
|
||||
// the torrent before it is deallocated
|
||||
if (m_torrent.is_seed())
|
||||
metadata();
|
||||
}
|
||||
|
||||
virtual boost::shared_ptr<peer_plugin> new_connection(
|
||||
peer_connection* pc);
|
||||
|
||||
std::vector<char> const& metadata() const
|
||||
{
|
||||
TORRENT_ASSERT(m_torrent.valid_metadata());
|
||||
|
||||
if (m_metadata.empty())
|
||||
{
|
||||
bencode(std::back_inserter(m_metadata)
|
||||
, m_torrent.torrent_file().create_info_metadata());
|
||||
|
||||
TORRENT_ASSERT(hasher(&m_metadata[0], m_metadata.size()).final()
|
||||
== m_torrent.torrent_file().info_hash());
|
||||
}
|
||||
TORRENT_ASSERT(!m_metadata.empty());
|
||||
return m_metadata;
|
||||
}
|
||||
|
||||
bool received_metadata(char const* buf, int size, int piece, int total_size)
|
||||
{
|
||||
if (m_torrent.valid_metadata()) return false;
|
||||
|
||||
if (m_metadata.empty())
|
||||
{
|
||||
// verify the total_size
|
||||
if (total_size <= 0 || total_size > 500 * 1024) return false;
|
||||
|
||||
m_metadata.resize(total_size);
|
||||
m_requested_metadata.resize(div_round_up(total_size, 16 * 1024), 0);
|
||||
}
|
||||
|
||||
if (piece < 0 || piece >= int(m_requested_metadata.size()))
|
||||
return false;
|
||||
|
||||
TORRENT_ASSERT(piece * 16 * 1024 + size <= int(m_metadata.size()));
|
||||
std::memcpy(&m_metadata[piece * 16 * 1024], buf, size);
|
||||
// mark this piece has 'have'
|
||||
m_requested_metadata[piece] = (std::numeric_limits<int>::max)();
|
||||
|
||||
bool have_all = std::count(m_requested_metadata.begin()
|
||||
, m_requested_metadata.end(), (std::numeric_limits<int>::max)())
|
||||
== int(m_requested_metadata.size());
|
||||
|
||||
if (!have_all) return false;
|
||||
|
||||
hasher h;
|
||||
h.update(&m_metadata[0], (int)m_metadata.size());
|
||||
sha1_hash info_hash = h.final();
|
||||
|
||||
if (info_hash != m_torrent.torrent_file().info_hash())
|
||||
{
|
||||
std::fill(m_requested_metadata.begin(), m_requested_metadata.end(), 0);
|
||||
|
||||
if (m_torrent.alerts().should_post(alert::info))
|
||||
{
|
||||
m_torrent.alerts().post_alert(metadata_failed_alert(
|
||||
m_torrent.get_handle(), "invalid metadata received from swarm"));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
entry metadata = bdecode(m_metadata.begin(), m_metadata.end());
|
||||
m_torrent.set_metadata(metadata);
|
||||
|
||||
// clear the storage for the bitfield
|
||||
std::vector<int>().swap(m_requested_metadata);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// returns a piece of the metadata that
|
||||
// we should request.
|
||||
int metadata_request();
|
||||
|
||||
// this is called from the peer_connection for
|
||||
// each piece of metadata it receives
|
||||
void metadata_progress(int total_size, int received)
|
||||
{
|
||||
m_metadata_progress += received;
|
||||
m_metadata_size = total_size;
|
||||
}
|
||||
|
||||
void piece_pass(int)
|
||||
{
|
||||
// if we became a seed, copy the metadata from
|
||||
// the torrent before it is deallocated
|
||||
if (m_torrent.is_seed())
|
||||
metadata();
|
||||
}
|
||||
|
||||
void metadata_size(int size)
|
||||
{
|
||||
if (m_metadata_size > 0 || size <= 0 || size > 500 * 1024) return;
|
||||
m_metadata_size = size;
|
||||
m_metadata.resize(size);
|
||||
m_requested_metadata.resize(div_round_up(size, 16 * 1024), 0);
|
||||
}
|
||||
|
||||
private:
|
||||
torrent& m_torrent;
|
||||
|
||||
// this buffer is filled with the info-section of
|
||||
// the metadata file while downloading it from
|
||||
// peers, and while sending it.
|
||||
// it is mutable because it's generated lazily
|
||||
mutable std::vector<char> m_metadata;
|
||||
|
||||
int m_metadata_progress;
|
||||
int m_metadata_size;
|
||||
|
||||
// this vector keeps track of how many times each meatdata
|
||||
// block has been requested
|
||||
// std::numeric_limits<int>::max() means we have the piece
|
||||
std::vector<int> m_requested_metadata;
|
||||
};
|
||||
|
||||
|
||||
struct ut_metadata_peer_plugin : peer_plugin
|
||||
{
|
||||
ut_metadata_peer_plugin(torrent& t, bt_peer_connection& pc
|
||||
, ut_metadata_plugin& tp)
|
||||
: m_message_index(0)
|
||||
, m_no_metadata(min_time())
|
||||
, m_torrent(t)
|
||||
, m_pc(pc)
|
||||
, m_tp(tp)
|
||||
{}
|
||||
|
||||
// can add entries to the extension handshake
|
||||
virtual void add_handshake(entry& h)
|
||||
{
|
||||
entry& messages = h["m"];
|
||||
messages["ut_metadata"] = 15;
|
||||
if (m_torrent.valid_metadata())
|
||||
h["metadata_size"] = m_tp.metadata().size();
|
||||
}
|
||||
|
||||
// called when the extension handshake from the other end is received
|
||||
virtual bool on_extension_handshake(entry const& h)
|
||||
{
|
||||
entry const* metadata_size = h.find_key("metadata_size");
|
||||
if (metadata_size && metadata_size->type() == entry::int_t)
|
||||
m_tp.metadata_size(metadata_size->integer());
|
||||
|
||||
entry const& messages = h["m"];
|
||||
if (entry const* index = messages.find_key("ut_metadata"))
|
||||
{
|
||||
m_message_index = index->integer();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_message_index = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void write_metadata_packet(int type, int piece)
|
||||
{
|
||||
TORRENT_ASSERT(type >= 0 && type <= 2);
|
||||
TORRENT_ASSERT(piece >= 0);
|
||||
TORRENT_ASSERT(!m_pc.associated_torrent().expired());
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_pc.m_logger) << time_now_string() << " ==> UT_METADATA [ "
|
||||
"type: " << type << " | piece: " << piece << " ]\n";
|
||||
#endif
|
||||
// abort if the peer doesn't support the metadata extension
|
||||
if (m_message_index == 0) return;
|
||||
|
||||
int total_size = 4; // msg_extended, m_message_index, 'd', ... , 'e'
|
||||
char pkt_header[7];
|
||||
|
||||
char prefix[200];
|
||||
int prefix_len = 0;
|
||||
char suffix[200];
|
||||
int suffix_len = std::sprintf(suffix, "8:msg_typei%de5:piecei%de", type, piece);
|
||||
|
||||
char const* metadata = 0;
|
||||
int metadata_piece_size = 0;
|
||||
|
||||
if (type == 1)
|
||||
{
|
||||
TORRENT_ASSERT(m_pc.associated_torrent().lock()->valid_metadata());
|
||||
int offset = piece * 16 * 1024;
|
||||
metadata = &m_tp.metadata()[0] + offset;
|
||||
metadata_piece_size = (std::min)(int(m_tp.metadata().size() - offset), 16 * 1024);
|
||||
TORRENT_ASSERT(metadata_piece_size > 0);
|
||||
TORRENT_ASSERT(offset >= 0);
|
||||
TORRENT_ASSERT(offset + metadata_piece_size <= int(m_tp.metadata().size()));
|
||||
|
||||
prefix_len = std::sprintf(prefix, "8:metadata%d:", metadata_piece_size);
|
||||
total_size += prefix_len + metadata_piece_size;
|
||||
|
||||
suffix_len += std::sprintf(suffix + suffix_len, "10:total_sizei%de", int(m_tp.metadata().size()));
|
||||
}
|
||||
|
||||
total_size += suffix_len;
|
||||
|
||||
suffix[suffix_len++] = 'e';
|
||||
suffix[suffix_len] = 0;
|
||||
|
||||
char* p = pkt_header;
|
||||
namespace io = detail;
|
||||
io::write_uint32(total_size, p);
|
||||
io::write_uint8(bt_peer_connection::msg_extended, p);
|
||||
io::write_uint8(m_message_index, p);
|
||||
io::write_uint8('d', p);
|
||||
|
||||
m_pc.send_buffer(pkt_header, 7);
|
||||
if (prefix_len) m_pc.send_buffer(prefix, prefix_len);
|
||||
if (metadata_piece_size) m_pc.append_send_buffer((char*)metadata, metadata_piece_size, &nop);
|
||||
m_pc.send_buffer(suffix, suffix_len);
|
||||
}
|
||||
|
||||
virtual bool on_extended(int length
|
||||
, int extended_msg, buffer::const_interval body)
|
||||
{
|
||||
if (extended_msg != 15) return false;
|
||||
if (m_message_index == 0) return false;
|
||||
|
||||
if (length > 17 * 1024)
|
||||
throw protocol_error("ut_metadata message larger than 17 kB");
|
||||
|
||||
if (!m_pc.packet_finished()) return true;
|
||||
|
||||
entry msg = bdecode(body.begin, body.end);
|
||||
|
||||
int type = msg["msg_type"].integer();
|
||||
int piece = msg["piece"].integer();
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_pc.m_logger) << time_now_string() << " <== UT_METADATA [ "
|
||||
"type: " << type << " | piece: " << piece << " ]\n";
|
||||
#endif
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 0: // request
|
||||
{
|
||||
if (!m_torrent.valid_metadata())
|
||||
{
|
||||
write_metadata_packet(2, piece);
|
||||
return true;
|
||||
}
|
||||
// TODO: put the request on the queue in some cases
|
||||
write_metadata_packet(1, piece);
|
||||
}
|
||||
break;
|
||||
case 1: // data
|
||||
{
|
||||
std::vector<int>::iterator i = std::find(m_sent_requests.begin()
|
||||
, m_sent_requests.end(), piece);
|
||||
|
||||
// unwanted piece?
|
||||
if (i == m_sent_requests.end()) return true;
|
||||
|
||||
m_sent_requests.erase(i);
|
||||
std::string const& d = msg["metadata"].string();
|
||||
entry const* total_size = msg.find_key("total_size");
|
||||
m_tp.received_metadata(d.c_str(), d.size(), piece
|
||||
, (total_size && total_size->type() == entry::int_t) ? total_size->integer() : 0);
|
||||
}
|
||||
break;
|
||||
case 2: // have no data
|
||||
{
|
||||
m_no_metadata = time_now();
|
||||
std::vector<int>::iterator i = std::find(m_sent_requests.begin()
|
||||
, m_sent_requests.end(), piece);
|
||||
// unwanted piece?
|
||||
if (i == m_sent_requests.end()) return true;
|
||||
m_sent_requests.erase(i);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw protocol_error("unknown metadata extension message: "
|
||||
+ boost::lexical_cast<std::string>(type));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void tick()
|
||||
{
|
||||
// if we don't have any metadata, and this peer
|
||||
// supports the request metadata extension
|
||||
// and we aren't currently waiting for a request
|
||||
// reply. Then, send a request for some metadata.
|
||||
if (!m_torrent.valid_metadata()
|
||||
&& m_message_index != 0
|
||||
&& m_sent_requests.size() < 2
|
||||
&& has_metadata())
|
||||
{
|
||||
int piece = m_tp.metadata_request();
|
||||
m_sent_requests.push_back(piece);
|
||||
write_metadata_packet(0, piece);
|
||||
}
|
||||
}
|
||||
|
||||
bool has_metadata() const
|
||||
{
|
||||
return time_now() - m_no_metadata > minutes(1);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// this is the message index the remote peer uses
|
||||
// for metadata extension messages.
|
||||
int m_message_index;
|
||||
|
||||
// this is set to the current time each time we get a
|
||||
// "I don't have metadata" message.
|
||||
ptime m_no_metadata;
|
||||
|
||||
// request queues
|
||||
std::vector<int> m_sent_requests;
|
||||
std::vector<int> m_incoming_requests;
|
||||
|
||||
torrent& m_torrent;
|
||||
bt_peer_connection& m_pc;
|
||||
ut_metadata_plugin& m_tp;
|
||||
};
|
||||
|
||||
boost::shared_ptr<peer_plugin> ut_metadata_plugin::new_connection(
|
||||
peer_connection* pc)
|
||||
{
|
||||
bt_peer_connection* c = dynamic_cast<bt_peer_connection*>(pc);
|
||||
if (!c) return boost::shared_ptr<peer_plugin>();
|
||||
return boost::shared_ptr<peer_plugin>(new ut_metadata_peer_plugin(m_torrent, *c, *this));
|
||||
}
|
||||
|
||||
int ut_metadata_plugin::metadata_request()
|
||||
{
|
||||
std::vector<int>::iterator i = std::min_element(
|
||||
m_requested_metadata.begin(), m_requested_metadata.end());
|
||||
|
||||
if (m_requested_metadata.empty())
|
||||
{
|
||||
// if we don't know how many pieces there are
|
||||
// just ask for piece 0
|
||||
m_requested_metadata.resize(1, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int piece = i - m_requested_metadata.begin();
|
||||
m_requested_metadata[piece] = piece;
|
||||
return piece;
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
boost::shared_ptr<torrent_plugin> create_ut_metadata_plugin(torrent* t, void*)
|
||||
{
|
||||
return boost::shared_ptr<torrent_plugin>(new ut_metadata_plugin(*t));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -7,18 +7,20 @@
|
|||
#include "test.hpp"
|
||||
#include "setup_transfer.hpp"
|
||||
#include "libtorrent/extensions/metadata_transfer.hpp"
|
||||
#include "libtorrent/extensions/ut_metadata.hpp"
|
||||
|
||||
using boost::filesystem::remove_all;
|
||||
using boost::tuples::ignore;
|
||||
|
||||
void test_transfer(bool clear_files = true, bool disconnect = false)
|
||||
void test_transfer(bool clear_files, bool disconnect
|
||||
, boost::shared_ptr<libtorrent::torrent_plugin> (*constructor)(libtorrent::torrent*, void*))
|
||||
{
|
||||
using namespace libtorrent;
|
||||
|
||||
session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48000, 49000));
|
||||
session ses2(fingerprint("LT", 0, 1, 0, 0), std::make_pair(49000, 50000));
|
||||
ses1.add_extension(&create_metadata_plugin);
|
||||
ses2.add_extension(&create_metadata_plugin);
|
||||
ses1.add_extension(constructor);
|
||||
ses2.add_extension(constructor);
|
||||
torrent_handle tor1;
|
||||
torrent_handle tor2;
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
|
@ -72,13 +74,18 @@ int test_main()
|
|||
using namespace boost::filesystem;
|
||||
|
||||
// test to disconnect one client prematurely
|
||||
test_transfer(true, true);
|
||||
|
||||
test_transfer(true, true, &create_metadata_plugin);
|
||||
// test where one has data and one doesn't
|
||||
test_transfer(true);
|
||||
|
||||
test_transfer(true, false, &create_metadata_plugin);
|
||||
// test where both have data (to trigger the file check)
|
||||
test_transfer(false);
|
||||
test_transfer(false, false, &create_metadata_plugin);
|
||||
|
||||
// test to disconnect one client prematurely
|
||||
test_transfer(true, true, &create_ut_metadata_plugin);
|
||||
// test where one has data and one doesn't
|
||||
test_transfer(true, false, &create_ut_metadata_plugin);
|
||||
// test where both have data (to trigger the file check)
|
||||
test_transfer(false, false, &create_ut_metadata_plugin);
|
||||
|
||||
remove_all("./tmp1");
|
||||
remove_all("./tmp2");
|
||||
|
|
Loading…
Reference in New Issue