*** empty log message ***

This commit is contained in:
Arvid Norberg 2004-01-04 04:29:13 +00:00
parent 97b387b196
commit 8a3d994416
8 changed files with 1315 additions and 1177 deletions

View File

@ -345,6 +345,8 @@ const char* buf;
entry e = bdecode(buf, buf + data_size);
</pre>
<p>Now we just need to know how to retrieve information from the <tt class="literal"><span class="pre">entry</span></tt>.</p>
<p>If <tt class="literal"><span class="pre">bdecode()</span></tt> encounters invalid encoded data in the range given to it
it will throw <a class="reference" href="#invalid-encoding">invalid_encoding</a>.</p>
</div>
<div class="section" id="entry">
<h2><a class="toc-backref" href="#id12" name="entry">entry</a></h2>
@ -392,7 +394,7 @@ public:
</pre>
<p>The <tt class="literal"><span class="pre">integer()</span></tt>, <tt class="literal"><span class="pre">string()</span></tt>, <tt class="literal"><span class="pre">list()</span></tt> and <tt class="literal"><span class="pre">dict()</span></tt> functions
are accessorts that return the respecive type. If the <tt class="literal"><span class="pre">entry</span></tt> object isn't of the
type you request, the accessor will throw <tt class="literal"><span class="pre">type_error</span></tt> (which derives from
type you request, the accessor will throw <a class="reference" href="#type-error">type_error</a> (which derives from
<tt class="literal"><span class="pre">std::runtime_error</span></tt>). You can ask an <tt class="literal"><span class="pre">entry</span></tt> for its type through the
<tt class="literal"><span class="pre">type()</span></tt> function.</p>
<p>The <tt class="literal"><span class="pre">print()</span></tt> function is there for debug purposes only.</p>
@ -541,7 +543,7 @@ was started.</p>
<p><tt class="literal"><span class="pre">set_max_uploads()</span></tt> sets the maximum number of peers that's unchoked at the same time on this
torrent. If you set this to -1, there will be no limit.</p>
<p><tt class="literal"><span class="pre">write_resume_data()</span></tt> takes a non-const reference to a char-vector, that vector will be filled
with the fast-resume data. For more information about hpw fast-resume works, see <a class="reference" href="#fast-resume">fast resume</a>.</p>
with the fast-resume data. For more information about how fast-resume works, see <a class="reference" href="#fast-resume">fast resume</a>.</p>
<div class="section" id="status">
<h3><a class="toc-backref" href="#id15" name="status">status()</a></h3>
<p><tt class="literal"><span class="pre">status()</span></tt> will return a structure with information about the status of this
@ -1140,7 +1142,7 @@ for each slot
4 bytes, the number of unfinished pieces
for each unfinished piece
4 bytes, index of the unfinished piece
blocks_per_piece / 32 bytes, the bitmask describing which
blocks_per_piece / 8 bytes, the bitmask describing which
blocks are finished in this piece.
</pre>
</div>

View File

@ -325,6 +325,8 @@ Or, if you have a raw char buffer::
Now we just need to know how to retrieve information from the ``entry``.
If ``bdecode()`` encounters invalid encoded data in the range given to it
it will throw invalid_encoding_.
@ -375,7 +377,7 @@ or a string. This is its synopsis::
The ``integer()``, ``string()``, ``list()`` and ``dict()`` functions
are accessorts that return the respecive type. If the ``entry`` object isn't of the
type you request, the accessor will throw ``type_error`` (which derives from
type you request, the accessor will throw type_error_ (which derives from
``std::runtime_error``). You can ask an ``entry`` for its type through the
``type()`` function.
@ -551,7 +553,7 @@ was started.
torrent. If you set this to -1, there will be no limit.
``write_resume_data()`` takes a non-const reference to a char-vector, that vector will be filled
with the fast-resume data. For more information about hpw fast-resume works, see `fast resume`_.
with the fast-resume data. For more information about how fast-resume works, see `fast resume`_.
status()
~~~~~~~~
@ -1211,7 +1213,7 @@ The format of the fast-resume data is as follows, given that all
4 bytes, the number of unfinished pieces
for each unfinished piece
4 bytes, index of the unfinished piece
blocks_per_piece / 32 bytes, the bitmask describing which
blocks_per_piece / 8 bytes, the bitmask describing which
blocks are finished in this piece.
Feedback

View File

@ -319,7 +319,9 @@ int main(int argc, char* argv[])
<< static_cast<const char*>((i->flags & peer_info::interesting)?"I":"_")
<< static_cast<const char*>((i->flags & peer_info::choked)?"C":"_")
<< static_cast<const char*>((i->flags & peer_info::remote_interested)?"i":"_")
<< static_cast<const char*>((i->flags & peer_info::remote_choked)?"c":"_") << "\n";
<< static_cast<const char*>((i->flags & peer_info::remote_choked)?"c":"_")
<< static_cast<const char*>((i->flags & peer_info::supports_extensions)?"e":"_")
<< "\n";
if (i->downloading_piece_index >= 0)
{

View File

@ -298,6 +298,9 @@ namespace libtorrent
- m_statistics.total_payload_upload();
}
bool support_extensions() const
{ return m_supports_extensions; }
#ifndef NDEBUG
boost::shared_ptr<logger> m_logger;
#endif
@ -310,6 +313,7 @@ namespace libtorrent
void send_bitfield();
void send_have(int index);
void send_handshake();
void send_extensions();
// is used during handshake
enum state
@ -330,6 +334,7 @@ namespace libtorrent
enum message_type
{
// standard messages
msg_choke = 0,
msg_unchoke,
msg_interested,
@ -338,7 +343,11 @@ namespace libtorrent
msg_bitfield,
msg_request,
msg_piece,
msg_cancel
msg_cancel,
// extension protocol message
msg_extensions = 20,
// extended messages
msg_gzip_piece
};
std::size_t m_packet_size;
@ -420,6 +429,11 @@ namespace libtorrent
// we have choked the upload to the peer
bool m_choked;
// this is set to true if the handshake from
// the peer indicated that it supports the
// extension protocol
bool m_supports_extensions;
// the pieces the other end have
std::vector<bool> m_have_piece;
@ -477,6 +491,14 @@ namespace libtorrent
// this value. If it sinks below a threshold, its
// considered a bad peer and will be banned.
int m_trust_points;
enum extension_index
{
gzip_piece,
num_supported_extensions
};
static const char* extension_names[num_supported_extensions];
unsigned char m_extension_messages[num_supported_extensions];
};
// this is called each time this peer generates some

View File

@ -46,7 +46,8 @@ namespace libtorrent
interesting = 0x1,
choked = 0x2,
remote_interested = 0x4,
remote_choked = 0x8
remote_choked = 0x8,
supports_extensions = 0x10
};
unsigned int flags;
address ip;

View File

@ -37,6 +37,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/peer_connection.hpp"
#include "libtorrent/session.hpp"
#include "libtorrent/identify_client.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#if defined(_MSC_VER)
#define for if (false) {} else for
@ -44,9 +46,15 @@ POSSIBILITY OF SUCH DAMAGE.
#define VERBOSE
using namespace libtorrent;
namespace libtorrent
{
libtorrent::peer_connection::peer_connection(
// the names of the extensions to look for in
// the extensions-message
const char* peer_connection::extension_names[] =
{ "gzip" };
peer_connection::peer_connection(
detail::session_impl& ses
, selector& sel
, torrent* t
@ -70,6 +78,7 @@ libtorrent::peer_connection::peer_connection(
, m_peer_choked(true)
, m_interesting(false)
, m_choked(true)
, m_supports_extensions(false)
, m_free_upload(0)
, m_send_quota(100)
, m_send_quota_left(100)
@ -83,6 +92,11 @@ libtorrent::peer_connection::peer_connection(
m_logger = m_ses.create_log(s->sender().as_string().c_str());
#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);
send_handshake();
// start in the state where we are trying to read the
@ -96,7 +110,7 @@ libtorrent::peer_connection::peer_connection(
send_bitfield();
}
libtorrent::peer_connection::peer_connection(
peer_connection::peer_connection(
detail::session_impl& ses
, selector& sel
, boost::shared_ptr<libtorrent::socket> s)
@ -118,6 +132,7 @@ libtorrent::peer_connection::peer_connection(
, m_peer_choked(true)
, m_interesting(false)
, m_choked(true)
, m_supports_extensions(false)
, m_free_upload(0)
, m_send_quota(100)
, m_send_quota_left(100)
@ -130,6 +145,11 @@ libtorrent::peer_connection::peer_connection(
m_logger = m_ses.create_log(s->sender().as_string().c_str());
#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
@ -139,7 +159,7 @@ libtorrent::peer_connection::peer_connection(
m_recv_buffer.resize(1);
}
libtorrent::peer_connection::~peer_connection()
peer_connection::~peer_connection()
{
m_selector.remove(m_socket);
if (m_attached_to_torrent)
@ -149,7 +169,7 @@ libtorrent::peer_connection::~peer_connection()
}
}
void libtorrent::peer_connection::set_send_quota(int num_bytes)
void peer_connection::set_send_quota(int num_bytes)
{
assert(num_bytes <= m_send_quota_limit || m_send_quota_limit == -1);
if (num_bytes > m_send_quota_limit && m_send_quota_limit!=-1) num_bytes = m_send_quota_limit;
@ -159,7 +179,7 @@ void libtorrent::peer_connection::set_send_quota(int num_bytes)
send_buffer_updated();
}
void libtorrent::peer_connection::send_handshake()
void peer_connection::send_handshake()
{
assert(m_send_buffer.size() == 0);
@ -185,6 +205,8 @@ void libtorrent::peer_connection::send_handshake()
m_send_buffer.begin() + pos
, m_send_buffer.begin() + pos + 8
, 0);
// indicate that we support the extension protocol
m_send_buffer[pos] = 0x80;
pos += 8;
// info hash
@ -207,7 +229,7 @@ void libtorrent::peer_connection::send_handshake()
send_buffer_updated();
}
boost::optional<piece_block_progress> libtorrent::peer_connection::downloading_piece() const
boost::optional<piece_block_progress> peer_connection::downloading_piece() const
{
// are we currently receiving a 'piece' message?
if (m_state != read_packet
@ -240,7 +262,7 @@ boost::optional<piece_block_progress> libtorrent::peer_connection::downloading_p
return boost::optional<piece_block_progress>(p);
}
bool libtorrent::peer_connection::dispatch_message(int received)
bool peer_connection::dispatch_message(int received)
{
assert(m_recv_pos >= received);
assert(m_recv_pos > 0);
@ -425,6 +447,45 @@ bool libtorrent::peer_connection::dispatch_message(int received)
}
// *************** EXTENSIONS ***************
case msg_extensions:
{
if (m_packet_size > 100 * 1024)
{
// too big extension message, abort
throw protocol_error("'extensions' message size > 100kB");
}
m_statistics.received_bytes(0, received);
if (m_recv_pos < m_packet_size) return false;
try
{
entry e = bdecode(m_recv_buffer.begin()+1, m_recv_buffer.end());
entry::dictionary_type& extensions = e.dict();
for (int i = 0; i < num_supported_extensions; ++i)
{
entry::dictionary_type::iterator f =
extensions.find(extension_names[i]);
if (f != extensions.end())
{
m_extension_messages[i] = f->second.integer();
}
}
}
catch(invalid_encoding& e)
{
throw protocol_error("'extensions' packet contains invalid bencoding");
}
catch(type_error& e)
{
throw protocol_error("'extensions' packet contains incorrect types");
}
break;
}
// *************** REQUEST ***************
case msg_request:
{
@ -635,7 +696,7 @@ bool libtorrent::peer_connection::dispatch_message(int received)
return true;
}
void libtorrent::peer_connection::cancel_block(piece_block block)
void peer_connection::cancel_block(piece_block block)
{
assert(block.piece_index >= 0);
assert(block.piece_index < m_torrent->torrent_file().num_pieces());
@ -681,7 +742,7 @@ void libtorrent::peer_connection::cancel_block(piece_block block)
send_buffer_updated();
}
void libtorrent::peer_connection::request_block(piece_block block)
void peer_connection::request_block(piece_block block)
{
assert(block.piece_index >= 0);
assert(block.piece_index < m_torrent->torrent_file().num_pieces());
@ -722,7 +783,7 @@ void libtorrent::peer_connection::request_block(piece_block block)
send_buffer_updated();
}
void libtorrent::peer_connection::send_bitfield()
void peer_connection::send_bitfield()
{
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " ==> BITFIELD\n";
@ -742,7 +803,41 @@ void libtorrent::peer_connection::send_bitfield()
send_buffer_updated();
}
void libtorrent::peer_connection::choke()
void peer_connection::send_extensions()
{
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " ==> EXTENSIONS\n";
#endif
assert(m_supports_extensions);
entry extension_list(entry::dictionary_t);
for (int i = 0; i < num_supported_extensions; ++i)
{
entry msg_index(entry::int_t);
msg_index.integer() = msg_extensions + 1 + i;
extension_list.dict()[extension_names[i]] = msg_index;
}
#ifndef NDEBUG
extension_list.print(std::cout);
#endif
m_send_buffer.push_back(msg_extensions);
// make room for message size
const int msg_size_pos = m_send_buffer.size();
m_send_buffer.resize(msg_size_pos + 4);
bencode(std::back_inserter(m_send_buffer), extension_list);
// write the length of the message
char* ptr = &m_send_buffer[msg_size_pos];
detail::write_int(m_send_buffer.size() - msg_size_pos + 1, ptr);
send_buffer_updated();
}
void peer_connection::choke()
{
if (m_choked) return;
char msg[] = {0,0,0,1,msg_choke};
@ -755,7 +850,7 @@ void libtorrent::peer_connection::choke()
send_buffer_updated();
}
void libtorrent::peer_connection::unchoke()
void peer_connection::unchoke()
{
if (!m_choked) return;
char msg[] = {0,0,0,1,msg_unchoke};
@ -767,7 +862,7 @@ void libtorrent::peer_connection::unchoke()
send_buffer_updated();
}
void libtorrent::peer_connection::interested()
void peer_connection::interested()
{
if (m_interesting) return;
char msg[] = {0,0,0,1,msg_interested};
@ -779,7 +874,7 @@ void libtorrent::peer_connection::interested()
send_buffer_updated();
}
void libtorrent::peer_connection::not_interested()
void peer_connection::not_interested()
{
if (!m_interesting) return;
char msg[] = {0,0,0,1,msg_not_interested};
@ -791,7 +886,7 @@ void libtorrent::peer_connection::not_interested()
send_buffer_updated();
}
void libtorrent::peer_connection::send_have(int index)
void peer_connection::send_have(int index)
{
const int packet_size = 9;
char msg[packet_size] = {0,0,0,5,msg_have};
@ -804,7 +899,7 @@ void libtorrent::peer_connection::send_have(int index)
send_buffer_updated();
}
void libtorrent::peer_connection::second_tick()
void peer_connection::second_tick()
{
m_statistics.second_tick();
m_send_quota_left = m_send_quota;
@ -852,7 +947,7 @@ void libtorrent::peer_connection::second_tick()
// --------------------------
// throws exception when the client should be disconnected
void libtorrent::peer_connection::receive_data()
void peer_connection::receive_data()
{
assert(!m_socket->is_blocking());
assert(m_packet_size > 0);
@ -945,11 +1040,16 @@ void libtorrent::peer_connection::receive_data()
// ok, now we have got enough of the handshake. Is this connection
// attached to a torrent?
if (m_torrent == 0)
{
// TODO: if the protocol is to be extended
// these 8 bytes would be used to describe the
// extensions available on the other side
if (m_recv_buffer[0] & 0x80)
{
m_supports_extensions = true;
}
if (m_torrent == 0)
{
// now, we have to see if there's a torrent with the
// info_hash we got from the peer
@ -988,6 +1088,8 @@ void libtorrent::peer_connection::receive_data()
}
}
if (m_supports_extensions) send_extensions();
m_state = read_peer_id;
m_packet_size = 20;
m_recv_pos = 0;
@ -1108,7 +1210,7 @@ void libtorrent::peer_connection::receive_data()
}
bool libtorrent::peer_connection::has_data() const throw()
bool peer_connection::has_data() const throw()
{
// if we have requests or pending data to be sent or announcements to be made
// we want to send data
@ -1123,7 +1225,7 @@ bool libtorrent::peer_connection::has_data() const throw()
// --------------------------
// throws exception when the client should be disconnected
void libtorrent::peer_connection::send_data()
void peer_connection::send_data()
{
assert(m_socket->is_writable());
assert(has_data());
@ -1299,7 +1401,7 @@ void libtorrent::peer_connection::send_data()
}
void libtorrent::peer_connection::keep_alive()
void peer_connection::keep_alive()
{
boost::posix_time::time_duration d;
d = boost::posix_time::second_clock::local_time() - m_last_sent;
@ -1314,3 +1416,4 @@ void libtorrent::peer_connection::keep_alive()
send_buffer_updated();
}
}
}

View File

@ -880,6 +880,7 @@ namespace libtorrent
m_impl.m_alerts.set_severity(s);
}
// TODO: store resume data as an entry instead
void detail::piece_checker_data::parse_resume_data(
const std::vector<char>* rd
, const torrent_info& info)
@ -920,7 +921,7 @@ namespace libtorrent
int num_unfinished = read_int(ptr);
if (num_unfinished < 0) return;
if (data.size() != 20 + (1 + num_slots + 2 + num_unfinished * (num_blocks_per_piece / 32 + 1)) * 4)
if (data.size() != 20 + (1 + num_slots + 2 + num_unfinished) * 4 + num_unfinished * (num_blocks_per_piece / 8))
return;
tmp_unfinished.reserve(num_unfinished);
@ -935,12 +936,13 @@ namespace libtorrent
|| p.index >= info.num_pieces())
return;
for (int j = 0; j < num_blocks_per_piece / 32; ++j)
const int num_bitmask_bytes = std::max(num_blocks_per_piece / 8, 1);
for (int j = 0; j < num_bitmask_bytes; ++j)
{
unsigned int bits = read_int(ptr);
for (int k = 0; k < 32; ++k)
unsigned char bits = read_uchar(ptr);
for (int k = 0; k < 8; ++k)
{
const int bit = j * 32 + k;
const int bit = j * 8 + k;
if (bits & (1 << bit))
p.finished_blocks[bit] = true;
}

View File

@ -231,12 +231,15 @@ namespace libtorrent
// the unsinished piece's index
detail::write_int(i->index, out);
// write
for (int j = 0; j < num_blocks_per_piece / 32; ++j)
// TODO: write the bitmask in correct byteorder
// TODO: make sure to read it in the correct order too
const int num_bitmask_bytes = std::max(num_blocks_per_piece / 8, 1);
for (int j = 0; j < num_bitmask_bytes; ++j)
{
unsigned int v = 0;
for (int k = 0; k < 32; ++k) v |= i->finished_blocks[j*32+k]?(1 << k):0;
detail::write_int(v, out);
unsigned char v = 0;
for (int k = 0; k < 8; ++k)
v |= i->finished_blocks[j*8+k]?(1 << k):0;
detail::write_uchar(v, out);
}
}
}
@ -337,6 +340,7 @@ namespace libtorrent
if (peer->is_choked()) p.flags |= peer_info::choked;
if (peer->is_peer_interested()) p.flags |= peer_info::remote_interested;
if (peer->has_peer_choked()) p.flags |= peer_info::remote_choked;
if (peer->support_extensions()) p.flags |= peer_info::supports_extensions;
p.pieces = peer->get_bitfield();
}