added tests for fast extension features + fixes
This commit is contained in:
parent
c4c8d0f533
commit
d29fbdc453
|
@ -739,6 +739,14 @@ namespace libtorrent
|
|||
m_allowed_fast.begin(), m_allowed_fast.end(), r.piece);
|
||||
if (i != m_allowed_fast.end()) m_allowed_fast.erase(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<int>::iterator i = std::find(m_suggested_pieces.begin()
|
||||
, m_suggested_pieces.end(), r.piece);
|
||||
if (i != m_suggested_pieces.end())
|
||||
m_suggested_pieces.erase(i);
|
||||
}
|
||||
|
||||
if (m_request_queue.empty())
|
||||
{
|
||||
if (m_download_queue.size() < 2)
|
||||
|
|
|
@ -1597,11 +1597,6 @@ namespace detail
|
|||
{
|
||||
assert(!save_path.empty());
|
||||
|
||||
// if you get this assert, you haven't managed to
|
||||
// open a listen port. call listen_on() first.
|
||||
if (m_listen_sockets.empty())
|
||||
throw std::runtime_error("no listen socket opened");
|
||||
|
||||
if (ti->begin_files() == ti->end_files())
|
||||
throw std::runtime_error("no files in torrent");
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ test-suite libtorrent :
|
|||
[ run test_storage.cpp ]
|
||||
[ run test_piece_picker.cpp ]
|
||||
# [ run test_entry.cpp ]
|
||||
[ run test_fast_extension.cpp ]
|
||||
[ run test_pe_crypto.cpp ]
|
||||
[ run test_bencoding.cpp ]
|
||||
[ run test_primitives.cpp ]
|
||||
|
|
|
@ -38,21 +38,12 @@ boost::intrusive_ptr<T> clone_ptr(boost::intrusive_ptr<T> const& ptr)
|
|||
return boost::intrusive_ptr<T>(new T(*ptr));
|
||||
}
|
||||
|
||||
boost::tuple<torrent_handle, torrent_handle, torrent_handle>
|
||||
setup_transfer(session* ses1, session* ses2, session* ses3
|
||||
, bool clear_files, bool use_metadata_transfer, bool connect_peers)
|
||||
boost::intrusive_ptr<torrent_info> create_torrent(std::ostream* file)
|
||||
{
|
||||
using namespace boost::filesystem;
|
||||
|
||||
assert(ses1);
|
||||
assert(ses2);
|
||||
|
||||
assert(ses1->id() != ses2->id());
|
||||
if (ses3)
|
||||
assert(ses3->id() != ses2->id());
|
||||
|
||||
char const* tracker_url = "http://non-existent-name.com/announce";
|
||||
|
||||
using namespace boost::filesystem;
|
||||
|
||||
boost::intrusive_ptr<torrent_info> t(new torrent_info);
|
||||
int total_size = 2 * 1024 * 1024;
|
||||
t->add_file(path("temporary"), total_size);
|
||||
|
@ -68,18 +59,40 @@ setup_transfer(session* ses1, session* ses2, session* ses3
|
|||
sha1_hash ph = hasher(&piece[0], piece.size()).final();
|
||||
for (int i = 0; i < num; ++i)
|
||||
t->set_hash(i, ph);
|
||||
t->create_torrent();
|
||||
|
||||
if (file)
|
||||
{
|
||||
while (total_size > 0)
|
||||
{
|
||||
file->write(&piece[0], (std::min)(int(piece.size()), total_size));
|
||||
total_size -= piece.size();
|
||||
}
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
boost::tuple<torrent_handle, torrent_handle, torrent_handle>
|
||||
setup_transfer(session* ses1, session* ses2, session* ses3
|
||||
, bool clear_files, bool use_metadata_transfer, bool connect_peers)
|
||||
{
|
||||
using namespace boost::filesystem;
|
||||
|
||||
assert(ses1);
|
||||
assert(ses2);
|
||||
|
||||
assert(ses1->id() != ses2->id());
|
||||
if (ses3)
|
||||
assert(ses3->id() != ses2->id());
|
||||
|
||||
|
||||
create_directory("./tmp1");
|
||||
std::ofstream file("./tmp1/temporary");
|
||||
while (total_size > 0)
|
||||
{
|
||||
file.write(&piece[0], (std::min)(int(piece.size()), total_size));
|
||||
total_size -= piece.size();
|
||||
}
|
||||
boost::intrusive_ptr<torrent_info> t = create_torrent(&file);
|
||||
file.close();
|
||||
if (clear_files) remove_all("./tmp2/temporary");
|
||||
|
||||
t->create_torrent();
|
||||
std::cerr << "generated torrent: " << t->info_hash() << std::endl;
|
||||
|
||||
ses1->set_severity_level(alert::debug);
|
||||
|
@ -95,7 +108,7 @@ setup_transfer(session* ses1, session* ses2, session* ses3
|
|||
if (ses3) tor3 = ses3->add_torrent(clone_ptr(t), "./tmp3");
|
||||
|
||||
if (use_metadata_transfer)
|
||||
tor2 = ses2->add_torrent(tracker_url
|
||||
tor2 = ses2->add_torrent("http://non-existent-name.com/announce"
|
||||
, t->info_hash(), 0, "./tmp2");
|
||||
else
|
||||
tor2 = ses2->add_torrent(clone_ptr(t), "./tmp2");
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
void test_sleep(int millisec);
|
||||
|
||||
boost::intrusive_ptr<libtorrent::torrent_info> create_torrent(std::ostream* file = 0);
|
||||
|
||||
boost::tuple<libtorrent::torrent_handle, libtorrent::torrent_handle
|
||||
, libtorrent::torrent_handle>
|
||||
setup_transfer(libtorrent::session* ses1, libtorrent::session* ses2
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
#include "test.hpp"
|
||||
#include "setup_transfer.hpp"
|
||||
#include "libtorrent/socket.hpp"
|
||||
#include "libtorrent/io.hpp"
|
||||
#include <cstring>
|
||||
#include <asio/read.hpp>
|
||||
#include <asio/write.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
int read_message(stream_socket& s, char* buffer)
|
||||
{
|
||||
using namespace libtorrent::detail;
|
||||
asio::read(s, asio::buffer(buffer, 4));
|
||||
char* ptr = buffer;
|
||||
int length = read_int32(ptr);
|
||||
|
||||
asio::read(s, asio::buffer(buffer, length));
|
||||
return length;
|
||||
}
|
||||
|
||||
char const* message_name[] = {"choke", "unchoke", "interested", "not_interested"
|
||||
, "have", "bitfield", "request", "piece", "cancel", "dht_port", "", "", ""
|
||||
, "suggest_piece", "have_all", "have_none", "reject_request", "allowed_fast"};
|
||||
|
||||
void send_allow_fast(stream_socket& s, int piece)
|
||||
{
|
||||
using namespace libtorrent::detail;
|
||||
char msg[] = "\0\0\0\x05\x11\0\0\0\0";
|
||||
char* ptr = msg + 5;
|
||||
write_int32(piece, ptr);
|
||||
asio::write(s, asio::buffer(msg, 9));
|
||||
}
|
||||
|
||||
void send_suggest_piece(stream_socket& s, int piece)
|
||||
{
|
||||
using namespace libtorrent::detail;
|
||||
char msg[] = "\0\0\0\x05\x0d\0\0\0\0";
|
||||
char* ptr = msg + 5;
|
||||
write_int32(piece, ptr);
|
||||
asio::write(s, asio::buffer(msg, 9));
|
||||
}
|
||||
|
||||
void send_unchoke(stream_socket& s)
|
||||
{
|
||||
char msg[] = "\0\0\0\x01\x01";
|
||||
asio::write(s, asio::buffer(msg, 5));
|
||||
}
|
||||
|
||||
void do_handshake(stream_socket& s, sha1_hash const& ih, char* buffer)
|
||||
{
|
||||
char handshake[] = "\x13" "BitTorrent protocol\0\0\0\0\0\0\0\x04"
|
||||
" " // space for info-hash
|
||||
"aaaaaaaaaaaaaaaaaaaa" // peer-id
|
||||
"\0\0\0\x01\x0e"; // have_all
|
||||
std::memcpy(handshake + 28, ih.begin(), 20);
|
||||
asio::write(s, asio::buffer(handshake, sizeof(handshake) - 1));
|
||||
|
||||
// read handshake
|
||||
asio::read(s, asio::buffer(buffer, 68));
|
||||
|
||||
TEST_CHECK(buffer[0] == 19);
|
||||
TEST_CHECK(std::memcmp(buffer + 1, "BitTorrent protocol", 19) == 0);
|
||||
|
||||
char* extensions = buffer + 20;
|
||||
// check for fast extension support
|
||||
TEST_CHECK(extensions[7] & 0x4);
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
// check for extension protocol support
|
||||
TEST_CHECK(extensions[5] & 0x10);
|
||||
#endif
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
// check for DHT support
|
||||
TEST_CHECK(extensions[7] & 0x1);
|
||||
#endif
|
||||
|
||||
TEST_CHECK(std::memcmp(buffer + 28, ih.begin(), 20) == 0);
|
||||
}
|
||||
|
||||
// makes sure that pieces that are allowed and then
|
||||
// rejected aren't requested again
|
||||
void test_reject_fast()
|
||||
{
|
||||
boost::intrusive_ptr<torrent_info> t = create_torrent();
|
||||
sha1_hash ih = t->info_hash();
|
||||
session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48000, 49000));
|
||||
ses1.add_torrent(t, "./tmp1");
|
||||
|
||||
test_sleep(2000);
|
||||
|
||||
io_service ios;
|
||||
stream_socket s(ios);
|
||||
s.connect(tcp::endpoint(address::from_string("127.0.0.1"), 48000));
|
||||
|
||||
char recv_buffer[1000];
|
||||
do_handshake(s, ih, recv_buffer);
|
||||
|
||||
std::vector<int> allowed_fast;
|
||||
allowed_fast.push_back(0);
|
||||
allowed_fast.push_back(1);
|
||||
allowed_fast.push_back(2);
|
||||
allowed_fast.push_back(3);
|
||||
|
||||
std::for_each(allowed_fast.begin(), allowed_fast.end()
|
||||
, bind(&send_allow_fast, boost::ref(s), _1));
|
||||
|
||||
while (!allowed_fast.empty())
|
||||
{
|
||||
read_message(s, recv_buffer);
|
||||
std::cerr << "msg: " << message_name[int(recv_buffer[0])] << std::endl;
|
||||
if (recv_buffer[0] != 0x6) continue;
|
||||
|
||||
using namespace libtorrent::detail;
|
||||
char* ptr = recv_buffer + 1;
|
||||
int piece = read_int32(ptr);
|
||||
|
||||
std::vector<int>::iterator i = std::find(allowed_fast.begin()
|
||||
, allowed_fast.end(), piece);
|
||||
TEST_CHECK(i != allowed_fast.end());
|
||||
if (i != allowed_fast.end())
|
||||
allowed_fast.erase(i);
|
||||
// send reject request
|
||||
recv_buffer[0] = 0x10;
|
||||
asio::write(s, asio::buffer("\0\0\0\x0d", 4));
|
||||
asio::write(s, asio::buffer(recv_buffer, 13));
|
||||
}
|
||||
}
|
||||
|
||||
void test_respect_suggest()
|
||||
{
|
||||
boost::intrusive_ptr<torrent_info> t = create_torrent();
|
||||
sha1_hash ih = t->info_hash();
|
||||
session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48000, 49000));
|
||||
ses1.add_torrent(t, "./tmp1");
|
||||
|
||||
test_sleep(2000);
|
||||
|
||||
io_service ios;
|
||||
stream_socket s(ios);
|
||||
s.connect(tcp::endpoint(address::from_string("127.0.0.1"), 48000));
|
||||
|
||||
char recv_buffer[1000];
|
||||
do_handshake(s, ih, recv_buffer);
|
||||
|
||||
std::vector<int> suggested;
|
||||
suggested.push_back(0);
|
||||
suggested.push_back(1);
|
||||
suggested.push_back(2);
|
||||
suggested.push_back(3);
|
||||
|
||||
std::for_each(suggested.begin(), suggested.end()
|
||||
, bind(&send_suggest_piece, boost::ref(s), _1));
|
||||
|
||||
send_unchoke(s);
|
||||
|
||||
int fail_counter = 100;
|
||||
while (!suggested.empty() && fail_counter > 0)
|
||||
{
|
||||
read_message(s, recv_buffer);
|
||||
std::cerr << "msg: " << message_name[int(recv_buffer[0])] << std::endl;
|
||||
fail_counter--;
|
||||
if (recv_buffer[0] != 0x6) continue;
|
||||
|
||||
using namespace libtorrent::detail;
|
||||
char* ptr = recv_buffer + 1;
|
||||
int piece = read_int32(ptr);
|
||||
|
||||
std::vector<int>::iterator i = std::find(suggested.begin()
|
||||
, suggested.end(), piece);
|
||||
TEST_CHECK(i != suggested.end());
|
||||
if (i != suggested.end())
|
||||
suggested.erase(i);
|
||||
// send reject request
|
||||
recv_buffer[0] = 0x10;
|
||||
asio::write(s, asio::buffer("\0\0\0\x0d", 4));
|
||||
asio::write(s, asio::buffer(recv_buffer, 13));
|
||||
}
|
||||
TEST_CHECK(fail_counter > 0);
|
||||
}
|
||||
|
||||
int test_main()
|
||||
{
|
||||
test_reject_fast();
|
||||
test_respect_suggest();
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue