added bencoding function and updated ut_metadata extension
This commit is contained in:
@@ -103,28 +103,35 @@ namespace libtorrent
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template <class OutIt>
|
template <class OutIt>
|
||||||
void write_string(OutIt& out, const std::string& val)
|
int write_string(OutIt& out, const std::string& val)
|
||||||
{
|
{
|
||||||
std::string::const_iterator end = val.begin() + val.length();
|
int ret = val.length();
|
||||||
std::copy(val.begin(), end, out);
|
std::string::const_iterator end = val.begin() + ret;
|
||||||
|
for (std::string::const_iterator i = val.begin()
|
||||||
|
, end(val.begin() + ret); i != end; ++i)
|
||||||
|
*out++ = *i;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_EXPORT char const* integer_to_str(char* buf, int size, entry::integer_type val);
|
TORRENT_EXPORT char const* integer_to_str(char* buf, int size, entry::integer_type val);
|
||||||
|
|
||||||
template <class OutIt>
|
template <class OutIt>
|
||||||
void write_integer(OutIt& out, entry::integer_type val)
|
int write_integer(OutIt& out, entry::integer_type val)
|
||||||
{
|
{
|
||||||
// the stack allocated buffer for keeping the
|
// the stack allocated buffer for keeping the
|
||||||
// decimal representation of the number can
|
// decimal representation of the number can
|
||||||
// not hold number bigger than this:
|
// not hold number bigger than this:
|
||||||
BOOST_STATIC_ASSERT(sizeof(entry::integer_type) <= 8);
|
BOOST_STATIC_ASSERT(sizeof(entry::integer_type) <= 8);
|
||||||
char buf[21];
|
char buf[21];
|
||||||
|
int ret = 0;
|
||||||
for (char const* str = integer_to_str(buf, 21, val);
|
for (char const* str = integer_to_str(buf, 21, val);
|
||||||
*str != 0; ++str)
|
*str != 0; ++str)
|
||||||
{
|
{
|
||||||
*out = *str;
|
*out = *str;
|
||||||
++out;
|
++out;
|
||||||
|
++ret;
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class OutIt>
|
template <class OutIt>
|
||||||
@@ -172,26 +179,31 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns the number of bytes written
|
||||||
template<class OutIt>
|
template<class OutIt>
|
||||||
void bencode_recursive(OutIt& out, const entry& e)
|
int bencode_recursive(OutIt& out, const entry& e)
|
||||||
{
|
{
|
||||||
|
int ret = 0;
|
||||||
switch(e.type())
|
switch(e.type())
|
||||||
{
|
{
|
||||||
case entry::int_t:
|
case entry::int_t:
|
||||||
write_char(out, 'i');
|
write_char(out, 'i');
|
||||||
write_integer(out, e.integer());
|
ret += write_integer(out, e.integer());
|
||||||
write_char(out, 'e');
|
write_char(out, 'e');
|
||||||
|
ret += 2;
|
||||||
break;
|
break;
|
||||||
case entry::string_t:
|
case entry::string_t:
|
||||||
write_integer(out, e.string().length());
|
ret += write_integer(out, e.string().length());
|
||||||
write_char(out, ':');
|
write_char(out, ':');
|
||||||
write_string(out, e.string());
|
ret += write_string(out, e.string());
|
||||||
|
ret += 1;
|
||||||
break;
|
break;
|
||||||
case entry::list_t:
|
case entry::list_t:
|
||||||
write_char(out, 'l');
|
write_char(out, 'l');
|
||||||
for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i)
|
for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i)
|
||||||
bencode_recursive(out, *i);
|
ret += bencode_recursive(out, *i);
|
||||||
write_char(out, 'e');
|
write_char(out, 'e');
|
||||||
|
ret += 2;
|
||||||
break;
|
break;
|
||||||
case entry::dictionary_t:
|
case entry::dictionary_t:
|
||||||
write_char(out, 'd');
|
write_char(out, 'd');
|
||||||
@@ -199,18 +211,21 @@ namespace libtorrent
|
|||||||
i != e.dict().end(); ++i)
|
i != e.dict().end(); ++i)
|
||||||
{
|
{
|
||||||
// write key
|
// write key
|
||||||
write_integer(out, i->first.length());
|
ret += write_integer(out, i->first.length());
|
||||||
write_char(out, ':');
|
write_char(out, ':');
|
||||||
write_string(out, i->first);
|
ret += write_string(out, i->first);
|
||||||
// write value
|
// write value
|
||||||
bencode_recursive(out, i->second);
|
ret += bencode_recursive(out, i->second);
|
||||||
|
ret += 1;
|
||||||
}
|
}
|
||||||
write_char(out, 'e');
|
write_char(out, 'e');
|
||||||
|
ret += 2;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// do nothing
|
// do nothing
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class InIt>
|
template<class InIt>
|
||||||
@@ -307,9 +322,9 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class OutIt>
|
template<class OutIt>
|
||||||
void bencode(OutIt out, const entry& e)
|
int bencode(OutIt out, const entry& e)
|
||||||
{
|
{
|
||||||
detail::bencode_recursive(out, e);
|
return detail::bencode_recursive(out, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class InIt>
|
template<class InIt>
|
||||||
@@ -329,6 +344,25 @@ namespace libtorrent
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class InIt>
|
||||||
|
entry bdecode(InIt start, InIt end, int& len)
|
||||||
|
{
|
||||||
|
entry e;
|
||||||
|
bool err = false;
|
||||||
|
InIt s = start;
|
||||||
|
detail::bdecode_recursive(start, end, e, err);
|
||||||
|
len = std::distance(s, start);
|
||||||
|
TORRENT_ASSERT(len >= 0);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
#ifdef BOOST_NO_EXCEPTIONS
|
||||||
|
return entry();
|
||||||
|
#else
|
||||||
|
throw invalid_encoding();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TORRENT_BENCODE_HPP_INCLUDED
|
#endif // TORRENT_BENCODE_HPP_INCLUDED
|
||||||
|
@@ -255,13 +255,9 @@ namespace libtorrent { namespace
|
|||||||
// abort if the peer doesn't support the metadata extension
|
// abort if the peer doesn't support the metadata extension
|
||||||
if (m_message_index == 0) return;
|
if (m_message_index == 0) return;
|
||||||
|
|
||||||
int total_size = 4; // msg_extended, m_message_index, 'd', ... , 'e'
|
entry e;
|
||||||
char pkt_header[7];
|
e["msg_type"] = type;
|
||||||
|
e["piece"] = piece;
|
||||||
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;
|
char const* metadata = 0;
|
||||||
int metadata_piece_size = 0;
|
int metadata_piece_size = 0;
|
||||||
@@ -269,35 +265,29 @@ namespace libtorrent { namespace
|
|||||||
if (type == 1)
|
if (type == 1)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(m_pc.associated_torrent().lock()->valid_metadata());
|
TORRENT_ASSERT(m_pc.associated_torrent().lock()->valid_metadata());
|
||||||
|
e["total_size"] = m_tp.metadata().size();
|
||||||
int offset = piece * 16 * 1024;
|
int offset = piece * 16 * 1024;
|
||||||
metadata = &m_tp.metadata()[0] + offset;
|
metadata = &m_tp.metadata()[0] + offset;
|
||||||
metadata_piece_size = (std::min)(int(m_tp.metadata().size() - offset), 16 * 1024);
|
metadata_piece_size = (std::min)(
|
||||||
|
int(m_tp.metadata().size() - offset), 16 * 1024);
|
||||||
TORRENT_ASSERT(metadata_piece_size > 0);
|
TORRENT_ASSERT(metadata_piece_size > 0);
|
||||||
TORRENT_ASSERT(offset >= 0);
|
TORRENT_ASSERT(offset >= 0);
|
||||||
TORRENT_ASSERT(offset + metadata_piece_size <= int(m_tp.metadata().size()));
|
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;
|
char msg[200];
|
||||||
|
char* header = msg;
|
||||||
suffix[suffix_len++] = 'e';
|
char* p = &msg[6];
|
||||||
suffix[suffix_len] = 0;
|
int len = bencode(p, e);
|
||||||
|
int total_size = 2 + len + metadata_piece_size;
|
||||||
char* p = pkt_header;
|
|
||||||
namespace io = detail;
|
namespace io = detail;
|
||||||
io::write_uint32(total_size, p);
|
io::write_uint32(total_size, header);
|
||||||
io::write_uint8(bt_peer_connection::msg_extended, p);
|
io::write_uint8(bt_peer_connection::msg_extended, header);
|
||||||
io::write_uint8(m_message_index, p);
|
io::write_uint8(m_message_index, header);
|
||||||
io::write_uint8('d', p);
|
|
||||||
|
|
||||||
m_pc.send_buffer(pkt_header, 7);
|
m_pc.send_buffer(msg, len + 6);
|
||||||
if (prefix_len) m_pc.send_buffer(prefix, prefix_len);
|
if (metadata_piece_size) m_pc.append_send_buffer(
|
||||||
if (metadata_piece_size) m_pc.append_send_buffer((char*)metadata, metadata_piece_size, &nop);
|
(char*)metadata, metadata_piece_size, &nop);
|
||||||
m_pc.send_buffer(suffix, suffix_len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool on_extended(int length
|
virtual bool on_extended(int length
|
||||||
@@ -311,7 +301,8 @@ namespace libtorrent { namespace
|
|||||||
|
|
||||||
if (!m_pc.packet_finished()) return true;
|
if (!m_pc.packet_finished()) return true;
|
||||||
|
|
||||||
entry msg = bdecode(body.begin, body.end);
|
int len;
|
||||||
|
entry msg = bdecode(body.begin, body.end, len);
|
||||||
|
|
||||||
int type = msg["msg_type"].integer();
|
int type = msg["msg_type"].integer();
|
||||||
int piece = msg["piece"].integer();
|
int piece = msg["piece"].integer();
|
||||||
@@ -343,9 +334,8 @@ namespace libtorrent { namespace
|
|||||||
if (i == m_sent_requests.end()) return true;
|
if (i == m_sent_requests.end()) return true;
|
||||||
|
|
||||||
m_sent_requests.erase(i);
|
m_sent_requests.erase(i);
|
||||||
std::string const& d = msg["metadata"].string();
|
|
||||||
entry const* total_size = msg.find_key("total_size");
|
entry const* total_size = msg.find_key("total_size");
|
||||||
m_tp.received_metadata(d.c_str(), d.size(), piece
|
m_tp.received_metadata(body.begin + len, body.left() - len, piece
|
||||||
, (total_size && total_size->type() == entry::int_t) ? total_size->integer() : 0);
|
, (total_size && total_size->type() == entry::int_t) ? total_size->integer() : 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user