refactored extensions and added a plugin interface. fixed file.cpp for windows
This commit is contained in:
@@ -45,6 +45,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "libtorrent/invariant_check.hpp"
|
||||
#include "libtorrent/io.hpp"
|
||||
#include "libtorrent/version.hpp"
|
||||
#include "libtorrent/extensions.hpp"
|
||||
#include "libtorrent/aux_/session_impl.hpp"
|
||||
|
||||
using namespace boost::posix_time;
|
||||
@@ -55,11 +56,6 @@ using libtorrent::aux::session_impl;
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
// the names of the extensions to look for in
|
||||
// the extensions-message
|
||||
const char* bt_peer_connection::extension_names[] =
|
||||
{ "", "LT_chat", "LT_metadata", "LT_peer_exchange" };
|
||||
|
||||
const bt_peer_connection::message_handler
|
||||
bt_peer_connection::m_message_handler[] =
|
||||
{
|
||||
@@ -85,17 +81,12 @@ namespace libtorrent
|
||||
, tcp::endpoint const& remote)
|
||||
: peer_connection(ses, tor, s, remote)
|
||||
, m_state(read_protocol_length)
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
, m_supports_extensions(false)
|
||||
#endif
|
||||
, m_supports_dht_port(false)
|
||||
, m_no_metadata(
|
||||
boost::gregorian::date(1970, boost::date_time::Jan, 1)
|
||||
, boost::posix_time::seconds(0))
|
||||
, m_metadata_request(
|
||||
boost::gregorian::date(1970, boost::date_time::Jan, 1)
|
||||
, boost::posix_time::seconds(0))
|
||||
, m_waiting_metadata_request(false)
|
||||
, m_metadata_progress(0)
|
||||
#ifndef NDEBUG
|
||||
, m_sent_bitfield(false)
|
||||
, m_in_constructor(true)
|
||||
#endif
|
||||
{
|
||||
@@ -103,11 +94,6 @@ namespace libtorrent
|
||||
(*m_logger) << "*** bt_peer_connection\n";
|
||||
#endif
|
||||
|
||||
// initialize the extension list to zero, since
|
||||
// we don't know which extensions the other
|
||||
// end supports yet
|
||||
std::fill(m_extension_messages, m_extension_messages + num_supported_extensions, 0);
|
||||
|
||||
write_handshake();
|
||||
|
||||
// start in the state where we are trying to read the
|
||||
@@ -133,25 +119,15 @@ namespace libtorrent
|
||||
, boost::shared_ptr<stream_socket> s)
|
||||
: peer_connection(ses, s)
|
||||
, m_state(read_protocol_length)
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
, m_supports_extensions(false)
|
||||
#endif
|
||||
, m_supports_dht_port(false)
|
||||
, m_no_metadata(
|
||||
boost::gregorian::date(1970, boost::date_time::Jan, 1)
|
||||
, boost::posix_time::seconds(0))
|
||||
, m_metadata_request(
|
||||
boost::gregorian::date(1970, boost::date_time::Jan, 1)
|
||||
, boost::posix_time::seconds(0))
|
||||
, m_waiting_metadata_request(false)
|
||||
, m_metadata_progress(0)
|
||||
#ifndef NDEBUG
|
||||
, m_sent_bitfield(false)
|
||||
, m_in_constructor(true)
|
||||
#endif
|
||||
{
|
||||
// initialize the extension list to zero, since
|
||||
// we don't know which extensions the other
|
||||
// end supports yet
|
||||
std::fill(m_extension_messages, m_extension_messages + num_supported_extensions, 0);
|
||||
|
||||
// we are not attached to any torrent yet.
|
||||
// we have to wait for the handshake to see
|
||||
// which torrent the connector want's to connect to
|
||||
@@ -169,6 +145,13 @@ namespace libtorrent
|
||||
{
|
||||
}
|
||||
|
||||
void bt_peer_connection::on_metadata()
|
||||
{
|
||||
boost::shared_ptr<torrent> t = associated_torrent().lock();
|
||||
assert(t);
|
||||
write_bitfield(t->pieces());
|
||||
}
|
||||
|
||||
void bt_peer_connection::write_dht_port(int listen_port)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
@@ -268,18 +251,17 @@ namespace libtorrent
|
||||
i.begin += string_len;
|
||||
|
||||
// 8 zeroes
|
||||
std::fill(
|
||||
i.begin
|
||||
, i.begin + 8
|
||||
, 0);
|
||||
std::fill(i.begin, i.begin + 8, 0);
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
// indicate that we support the DHT messages
|
||||
*(i.begin + 7) = 0x01;
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
// we support extensions
|
||||
*(i.begin + 5) = 0x10;
|
||||
#endif
|
||||
|
||||
i.begin += 8;
|
||||
|
||||
@@ -369,6 +351,14 @@ namespace libtorrent
|
||||
m_statistics.received_bytes(0, received);
|
||||
if (!packet_finished()) return;
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
{
|
||||
if ((*i)->on_choke()) return;
|
||||
}
|
||||
#endif
|
||||
|
||||
incoming_choke();
|
||||
}
|
||||
|
||||
@@ -386,6 +376,14 @@ namespace libtorrent
|
||||
m_statistics.received_bytes(0, received);
|
||||
if (!packet_finished()) return;
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
{
|
||||
if ((*i)->on_unchoke()) return;
|
||||
}
|
||||
#endif
|
||||
|
||||
incoming_unchoke();
|
||||
}
|
||||
|
||||
@@ -403,6 +401,14 @@ namespace libtorrent
|
||||
m_statistics.received_bytes(0, received);
|
||||
if (!packet_finished()) return;
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
{
|
||||
if ((*i)->on_interested()) return;
|
||||
}
|
||||
#endif
|
||||
|
||||
incoming_interested();
|
||||
}
|
||||
|
||||
@@ -420,6 +426,14 @@ namespace libtorrent
|
||||
m_statistics.received_bytes(0, received);
|
||||
if (!packet_finished()) return;
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
{
|
||||
if ((*i)->on_not_interested()) return;
|
||||
}
|
||||
#endif
|
||||
|
||||
incoming_not_interested();
|
||||
}
|
||||
|
||||
@@ -442,6 +456,14 @@ namespace libtorrent
|
||||
const char* ptr = recv_buffer.begin + 1;
|
||||
int index = detail::read_int32(ptr);
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
{
|
||||
if ((*i)->on_have(index)) return;
|
||||
}
|
||||
#endif
|
||||
|
||||
incoming_have(index);
|
||||
}
|
||||
|
||||
@@ -482,6 +504,15 @@ namespace libtorrent
|
||||
// (since it doesn't exist yet)
|
||||
for (int i = 0; i < (int)bitfield.size(); ++i)
|
||||
bitfield[i] = (recv_buffer[1 + (i>>3)] & (1 << (7 - (i&7)))) != 0;
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
{
|
||||
if ((*i)->on_bitfield(bitfield)) return;
|
||||
}
|
||||
#endif
|
||||
|
||||
incoming_bitfield(bitfield);
|
||||
}
|
||||
|
||||
@@ -507,6 +538,14 @@ namespace libtorrent
|
||||
r.start = detail::read_int32(ptr);
|
||||
r.length = detail::read_int32(ptr);
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
{
|
||||
if ((*i)->on_request(r)) return;
|
||||
}
|
||||
#endif
|
||||
|
||||
incoming_request(r);
|
||||
}
|
||||
|
||||
@@ -551,6 +590,14 @@ namespace libtorrent
|
||||
p.start = detail::read_int32(ptr);
|
||||
p.length = packet_size() - 9;
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
{
|
||||
if ((*i)->on_piece(p, recv_buffer.begin + 9)) return;
|
||||
}
|
||||
#endif
|
||||
|
||||
incoming_piece(p, recv_buffer.begin + 9);
|
||||
}
|
||||
|
||||
@@ -576,6 +623,14 @@ namespace libtorrent
|
||||
r.start = detail::read_int32(ptr);
|
||||
r.length = detail::read_int32(ptr);
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
{
|
||||
if ((*i)->on_cancel(r)) return;
|
||||
}
|
||||
#endif
|
||||
|
||||
incoming_cancel(r);
|
||||
}
|
||||
|
||||
@@ -618,33 +673,33 @@ namespace libtorrent
|
||||
throw protocol_error("'extended' message sent before proper handshake");
|
||||
|
||||
buffer::const_interval recv_buffer = receive_buffer();
|
||||
if (recv_buffer.end - recv_buffer.begin < 2) return;
|
||||
if (recv_buffer.left() < 2) return;
|
||||
|
||||
assert(*recv_buffer.begin == msg_extended);
|
||||
++recv_buffer.begin;
|
||||
|
||||
int extended_id = detail::read_uint8(recv_buffer.begin);
|
||||
|
||||
if (extended_id > 0 && extended_id < num_supported_extensions
|
||||
&& !m_ses.extension_enabled(extended_id))
|
||||
throw protocol_error("'extended' message using disabled extension");
|
||||
|
||||
switch (extended_id)
|
||||
if (extended_id == 0)
|
||||
{
|
||||
case extended_handshake:
|
||||
on_extended_handshake(); break;
|
||||
case extended_chat_message:
|
||||
on_chat(); break;
|
||||
case extended_metadata_message:
|
||||
on_metadata(); break;
|
||||
case extended_peer_exchange_message:
|
||||
on_peer_exchange(); break;
|
||||
default:
|
||||
throw protocol_error("unknown extended message id: "
|
||||
+ boost::lexical_cast<std::string>(extended_id));
|
||||
};
|
||||
}
|
||||
on_extended_handshake();
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
{
|
||||
if ((*i)->on_extended(packet_size() - 2, extended_id
|
||||
, recv_buffer))
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
throw protocol_error("unknown extended message id: "
|
||||
+ boost::lexical_cast<std::string>(extended_id));
|
||||
}
|
||||
/*
|
||||
void bt_peer_connection::write_chat_message(const std::string& msg)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
@@ -669,9 +724,9 @@ namespace libtorrent
|
||||
assert(i.begin == i.end);
|
||||
setup_send();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void bt_peer_connection::on_extended_handshake() try
|
||||
void bt_peer_connection::on_extended_handshake()
|
||||
{
|
||||
if (!packet_finished()) return;
|
||||
|
||||
@@ -679,35 +734,38 @@ namespace libtorrent
|
||||
assert(t);
|
||||
|
||||
buffer::const_interval recv_buffer = receive_buffer();
|
||||
|
||||
entry root = bdecode(recv_buffer.begin + 2, recv_buffer.end);
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
entry root;
|
||||
try
|
||||
{
|
||||
root = bdecode(recv_buffer.begin + 2, recv_buffer.end);
|
||||
}
|
||||
catch (std::exception& exc)
|
||||
{
|
||||
#ifdef TORRENT_VERBOSE_LOGGIGN
|
||||
(*m_logger) << "invalid extended handshake: " << exc.what() << "\n";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGIGN
|
||||
std::stringstream ext;
|
||||
root.print(ext);
|
||||
(*m_logger) << "<== EXTENDED HANDSHAKE: \n" << ext.str();
|
||||
#endif
|
||||
|
||||
if (entry* msgs = root.find_key("m"))
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end;)
|
||||
{
|
||||
if (msgs->type() == entry::dictionary_t)
|
||||
{
|
||||
// this must be the initial handshake message
|
||||
// lets see if any of our extensions are supported
|
||||
// if not, we will signal no extensions support to the upper layer
|
||||
for (int i = 1; i < num_supported_extensions; ++i)
|
||||
{
|
||||
if (entry* f = msgs->find_key(extension_names[i]))
|
||||
{
|
||||
m_extension_messages[i] = (int)f->integer();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_extension_messages[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// a false return value means that the extension
|
||||
// isn't supported by the other end. So, it is removed.
|
||||
if (!(*i)->on_extension_handshake(root))
|
||||
i = m_extensions.erase(i);
|
||||
else
|
||||
++i;
|
||||
}
|
||||
#endif
|
||||
|
||||
// there is supposed to be a remote listen port
|
||||
if (entry* listen_port = root.find_key("p"))
|
||||
@@ -736,154 +794,6 @@ namespace libtorrent
|
||||
m_max_out_request_queue = 1;
|
||||
}
|
||||
}
|
||||
catch (std::exception& exc)
|
||||
{
|
||||
#ifdef TORRENT_VERBOSE_LOGGIGN
|
||||
(*m_logger) << "invalid extended handshake: " << exc.what() << "\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// ----------- CHAT ------------
|
||||
// -----------------------------
|
||||
|
||||
void bt_peer_connection::on_chat()
|
||||
{
|
||||
if (packet_size() > 2 * 1024)
|
||||
throw protocol_error("CHAT message larger than 2 kB");
|
||||
|
||||
if (!packet_finished()) return;
|
||||
|
||||
try
|
||||
{
|
||||
boost::shared_ptr<torrent> t = associated_torrent().lock();
|
||||
assert(t);
|
||||
|
||||
buffer::const_interval recv_buffer = receive_buffer();
|
||||
entry d = bdecode(recv_buffer.begin + 2, recv_buffer.end);
|
||||
const std::string& str = d["msg"].string();
|
||||
|
||||
if (t->alerts().should_post(alert::critical))
|
||||
{
|
||||
t->alerts().post_alert(
|
||||
chat_message_alert(
|
||||
t->get_handle()
|
||||
, remote(), str));
|
||||
}
|
||||
|
||||
}
|
||||
catch (invalid_encoding&)
|
||||
{
|
||||
// TODO: post an alert about the invalid chat message
|
||||
return;
|
||||
// throw protocol_error("invalid bencoding in CHAT message");
|
||||
}
|
||||
catch (type_error&)
|
||||
{
|
||||
// TODO: post an alert about the invalid chat message
|
||||
return;
|
||||
// throw protocol_error("invalid types in bencoded CHAT message");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// --------- METADATA ----------
|
||||
// -----------------------------
|
||||
|
||||
void bt_peer_connection::on_metadata()
|
||||
{
|
||||
boost::shared_ptr<torrent> t = associated_torrent().lock();
|
||||
assert(t);
|
||||
|
||||
if (packet_size() > 500 * 1024)
|
||||
throw protocol_error("metadata message larger than 500 kB");
|
||||
|
||||
if (!packet_finished()) return;
|
||||
|
||||
buffer::const_interval recv_buffer = receive_buffer();
|
||||
recv_buffer.begin += 2;
|
||||
int type = detail::read_uint8(recv_buffer.begin);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 0: // request
|
||||
{
|
||||
int start = detail::read_uint8(recv_buffer.begin);
|
||||
int size = detail::read_uint8(recv_buffer.begin) + 1;
|
||||
|
||||
if (packet_size() != 5)
|
||||
{
|
||||
// invalid metadata request
|
||||
throw protocol_error("invalid metadata request");
|
||||
}
|
||||
|
||||
write_metadata(std::make_pair(start, size));
|
||||
}
|
||||
break;
|
||||
case 1: // data
|
||||
{
|
||||
if (recv_buffer.end - recv_buffer.begin < 8) return;
|
||||
int total_size = detail::read_int32(recv_buffer.begin);
|
||||
int offset = detail::read_int32(recv_buffer.begin);
|
||||
int data_size = packet_size() - 2 - 9;
|
||||
|
||||
if (total_size > 500 * 1024)
|
||||
throw protocol_error("metadata size larger than 500 kB");
|
||||
if (total_size <= 0)
|
||||
throw protocol_error("invalid metadata size");
|
||||
if (offset > total_size || offset < 0)
|
||||
throw protocol_error("invalid metadata offset");
|
||||
if (offset + data_size > total_size)
|
||||
throw protocol_error("invalid metadata message");
|
||||
|
||||
t->metadata_progress(total_size
|
||||
, recv_buffer.left() - m_metadata_progress);
|
||||
m_metadata_progress = recv_buffer.left();
|
||||
if (!packet_finished()) return;
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
using namespace boost::posix_time;
|
||||
(*m_logger) << to_simple_string(second_clock::universal_time())
|
||||
<< " <== METADATA [ tot: " << total_size << " offset: "
|
||||
<< offset << " size: " << data_size << " ]\n";
|
||||
#endif
|
||||
|
||||
m_waiting_metadata_request = false;
|
||||
t->received_metadata(recv_buffer.begin, data_size
|
||||
, offset, total_size);
|
||||
m_metadata_progress = 0;
|
||||
}
|
||||
break;
|
||||
case 2: // have no data
|
||||
if (!packet_finished()) return;
|
||||
|
||||
m_no_metadata = second_clock::universal_time();
|
||||
if (m_waiting_metadata_request)
|
||||
t->cancel_metadata_request(m_last_metadata_request);
|
||||
m_waiting_metadata_request = false;
|
||||
break;
|
||||
default:
|
||||
throw protocol_error("unknown metadata extension message: "
|
||||
+ boost::lexical_cast<std::string>(type));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// ------ PEER EXCHANGE --------
|
||||
// -----------------------------
|
||||
|
||||
void bt_peer_connection::on_peer_exchange()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool bt_peer_connection::has_metadata() const
|
||||
{
|
||||
using namespace boost::posix_time;
|
||||
return second_clock::universal_time() - m_no_metadata > minutes(5);
|
||||
}
|
||||
|
||||
bool bt_peer_connection::dispatch_message(int received)
|
||||
{
|
||||
@@ -901,6 +811,17 @@ namespace libtorrent
|
||||
|| packet_type >= num_supported_messages
|
||||
|| m_message_handler[packet_type] == 0)
|
||||
{
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
{
|
||||
if ((*i)->on_unknown_message(packet_size(), packet_type
|
||||
, buffer::const_interval(recv_buffer.begin+1
|
||||
, recv_buffer.end)))
|
||||
return packet_finished();
|
||||
}
|
||||
#endif
|
||||
|
||||
throw protocol_error("unknown message id: "
|
||||
+ boost::lexical_cast<std::string>(packet_type)
|
||||
+ " size: " + boost::lexical_cast<std::string>(packet_size()));
|
||||
@@ -911,9 +832,7 @@ namespace libtorrent
|
||||
// call the correct handler for this packet type
|
||||
(this->*m_message_handler[packet_type])(received);
|
||||
|
||||
if (!packet_finished()) return false;
|
||||
|
||||
return true;
|
||||
return packet_finished();
|
||||
}
|
||||
|
||||
void bt_peer_connection::write_keepalive()
|
||||
@@ -972,103 +891,14 @@ namespace libtorrent
|
||||
setup_send();
|
||||
}
|
||||
|
||||
void bt_peer_connection::write_metadata(std::pair<int, int> req)
|
||||
{
|
||||
assert(req.first >= 0);
|
||||
assert(req.second > 0);
|
||||
assert(req.second <= 256);
|
||||
assert(req.first + req.second <= 256);
|
||||
assert(!associated_torrent().expired());
|
||||
INVARIANT_CHECK;
|
||||
|
||||
// abort if the peer doesn't support the metadata extension
|
||||
if (!supports_extension(extended_metadata_message)) return;
|
||||
|
||||
boost::shared_ptr<torrent> t = associated_torrent().lock();
|
||||
assert(t);
|
||||
|
||||
if (t->valid_metadata())
|
||||
{
|
||||
std::pair<int, int> offset
|
||||
= req_to_offset(req, (int)t->metadata().size());
|
||||
|
||||
buffer::interval i = allocate_send_buffer(15 + offset.second);
|
||||
|
||||
// yes, we have metadata, send it
|
||||
detail::write_uint32(11 + offset.second, i.begin);
|
||||
detail::write_uint8(msg_extended, i.begin);
|
||||
detail::write_uint8(m_extension_messages[extended_metadata_message]
|
||||
, i.begin);
|
||||
// means 'data packet'
|
||||
detail::write_uint8(1, i.begin);
|
||||
detail::write_uint32((int)t->metadata().size(), i.begin);
|
||||
detail::write_uint32(offset.first, i.begin);
|
||||
std::vector<char> const& metadata = t->metadata();
|
||||
std::copy(metadata.begin() + offset.first
|
||||
, metadata.begin() + offset.first + offset.second, i.begin);
|
||||
i.begin += offset.second;
|
||||
assert(i.begin == i.end);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer::interval i = allocate_send_buffer(4 + 3);
|
||||
// we don't have the metadata, reply with
|
||||
// don't have-message
|
||||
detail::write_uint32(1 + 2, i.begin);
|
||||
detail::write_uint8(msg_extended, i.begin);
|
||||
detail::write_uint8(m_extension_messages[extended_metadata_message]
|
||||
, i.begin);
|
||||
// means 'have no data'
|
||||
detail::write_uint8(2, i.begin);
|
||||
assert(i.begin == i.end);
|
||||
}
|
||||
setup_send();
|
||||
}
|
||||
|
||||
void bt_peer_connection::write_metadata_request(std::pair<int, int> req)
|
||||
{
|
||||
assert(req.first >= 0);
|
||||
assert(req.second > 0);
|
||||
assert(req.first + req.second <= 256);
|
||||
assert(!associated_torrent().expired());
|
||||
assert(!associated_torrent().lock()->valid_metadata());
|
||||
INVARIANT_CHECK;
|
||||
|
||||
int start = req.first;
|
||||
int size = req.second;
|
||||
|
||||
// abort if the peer doesn't support the metadata extension
|
||||
if (!supports_extension(extended_metadata_message)) return;
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
using namespace boost::posix_time;
|
||||
(*m_logger) << to_simple_string(second_clock::universal_time())
|
||||
<< " ==> METADATA_REQUEST [ start: " << req.first
|
||||
<< " size: " << req.second << " ]\n";
|
||||
#endif
|
||||
|
||||
buffer::interval i = allocate_send_buffer(9);
|
||||
|
||||
detail::write_uint32(1 + 1 + 3, i.begin);
|
||||
detail::write_uint8(msg_extended, i.begin);
|
||||
detail::write_uint8(m_extension_messages[extended_metadata_message]
|
||||
, i.begin);
|
||||
// means 'request data'
|
||||
detail::write_uint8(0, i.begin);
|
||||
detail::write_uint8(start, i.begin);
|
||||
detail::write_uint8(size - 1, i.begin);
|
||||
assert(i.begin == i.end);
|
||||
setup_send();
|
||||
}
|
||||
|
||||
void bt_peer_connection::write_bitfield(std::vector<bool> const& bitfield)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
boost::shared_ptr<torrent> t = associated_torrent().lock();
|
||||
assert(t);
|
||||
|
||||
if (t->num_pieces() == 0) return;
|
||||
assert(m_sent_bitfield == false);
|
||||
assert(t->valid_metadata());
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
using namespace boost::posix_time;
|
||||
@@ -1096,9 +926,13 @@ namespace libtorrent
|
||||
i.begin[c >> 3] |= 1 << (7 - (c & 7));
|
||||
}
|
||||
assert(i.end - i.begin == ((int)bitfield.size() + 7) / 8);
|
||||
#ifndef NDEBUG
|
||||
m_sent_bitfield = true;
|
||||
#endif
|
||||
setup_send();
|
||||
}
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
void bt_peer_connection::write_extensions()
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
@@ -1113,14 +947,6 @@ namespace libtorrent
|
||||
entry handshake(entry::dictionary_t);
|
||||
entry extension_list(entry::dictionary_t);
|
||||
|
||||
for (int i = 1; i < num_supported_extensions; ++i)
|
||||
{
|
||||
// if this specific extension is disabled
|
||||
// just don't add it to the supported set
|
||||
if (!m_ses.extension_enabled(i)) continue;
|
||||
extension_list[extension_names[i]] = i;
|
||||
}
|
||||
|
||||
handshake["m"] = extension_list;
|
||||
handshake["p"] = m_ses.listen_port();
|
||||
handshake["v"] = m_ses.settings().user_agent;
|
||||
@@ -1130,6 +956,14 @@ namespace libtorrent
|
||||
handshake["ip"] = remote_address;
|
||||
handshake["reqq"] = m_ses.settings().max_allowed_in_request_queue;
|
||||
|
||||
// loop backwards, to make the first extension be the last
|
||||
// to fill in the handshake (i.e. give the first extensions priority)
|
||||
for (extension_list_t::reverse_iterator i = m_extensions.rbegin()
|
||||
, end(m_extensions.rend()); i != end; ++i)
|
||||
{
|
||||
(*i)->add_handshake(handshake);
|
||||
}
|
||||
|
||||
std::vector<char> msg;
|
||||
bencode(std::back_inserter(msg), handshake);
|
||||
|
||||
@@ -1140,7 +974,7 @@ namespace libtorrent
|
||||
detail::write_int32((int)msg.size() + 2, i.begin);
|
||||
detail::write_uint8(msg_extended, i.begin);
|
||||
// signal handshake message
|
||||
detail::write_uint8(extended_handshake, i.begin);
|
||||
detail::write_uint8(0, i.begin);
|
||||
|
||||
std::copy(msg.begin(), msg.end(), i.begin);
|
||||
i.begin += msg.size();
|
||||
@@ -1154,6 +988,7 @@ namespace libtorrent
|
||||
|
||||
setup_send();
|
||||
}
|
||||
#endif
|
||||
|
||||
void bt_peer_connection::write_choke()
|
||||
{
|
||||
@@ -1232,7 +1067,7 @@ namespace libtorrent
|
||||
// --------------------------
|
||||
|
||||
// throws exception when the client should be disconnected
|
||||
void bt_peer_connection::on_receive(const asio::error& error
|
||||
void bt_peer_connection::on_receive(asio::error_code const& error
|
||||
, std::size_t bytes_transferred)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
@@ -1330,8 +1165,10 @@ namespace libtorrent
|
||||
(*m_logger) << "supports LT/uT extensions\n";
|
||||
#endif
|
||||
|
||||
if ((recv_buffer[5] & 0x10) && m_ses.extensions_enabled())
|
||||
#ifndef DISABLE_EXTENSIONS
|
||||
if ((recv_buffer[5] & 0x10))
|
||||
m_supports_extensions = true;
|
||||
#endif
|
||||
if (recv_buffer[7] & 0x01)
|
||||
m_supports_dht_port = true;
|
||||
|
||||
@@ -1354,7 +1191,8 @@ namespace libtorrent
|
||||
// yes, we found the torrent
|
||||
// reply with our handshake
|
||||
write_handshake();
|
||||
write_bitfield(t->pieces());
|
||||
if (t->valid_metadata())
|
||||
write_bitfield(t->pieces());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1369,6 +1207,8 @@ namespace libtorrent
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
if (m_supports_dht_port && m_ses.m_dht)
|
||||
write_dht_port(m_ses.kad_settings().service_port);
|
||||
@@ -1422,7 +1262,23 @@ namespace libtorrent
|
||||
if (pid == m_ses.get_peer_id())
|
||||
throw std::runtime_error("closing connection to ourself");
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end;)
|
||||
{
|
||||
if (!(*i)->on_handshake())
|
||||
{
|
||||
i = m_extensions.erase(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_supports_extensions) write_extensions();
|
||||
#endif
|
||||
|
||||
/*
|
||||
if (!m_active)
|
||||
{
|
||||
@@ -1487,7 +1343,7 @@ namespace libtorrent
|
||||
// --------------------------
|
||||
|
||||
// throws exception when the client should be disconnected
|
||||
void bt_peer_connection::on_sent(asio::error const& error
|
||||
void bt_peer_connection::on_sent(asio::error_code const& error
|
||||
, std::size_t bytes_transferred)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
@@ -1528,7 +1384,7 @@ namespace libtorrent
|
||||
m_statistics.sent_bytes(amount_payload, bytes_transferred - amount_payload);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void bt_peer_connection::on_tick()
|
||||
{
|
||||
boost::shared_ptr<torrent> t = associated_torrent().lock();
|
||||
@@ -1549,7 +1405,7 @@ namespace libtorrent
|
||||
m_metadata_request = second_clock::universal_time();
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
#ifndef NDEBUG
|
||||
void bt_peer_connection::check_invariant() const
|
||||
{
|
||||
|
Reference in New Issue
Block a user