From e38c0c9cdcc11f1f9b46bb3832685326f7f939fb Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sat, 22 Dec 2007 08:15:05 +0000 Subject: [PATCH] added bencoding function and updated ut_metadata extension --- include/libtorrent/bencode.hpp | 62 ++++++++++++++++++++++++++-------- src/ut_metadata.cpp | 50 +++++++++++---------------- 2 files changed, 68 insertions(+), 44 deletions(-) diff --git a/include/libtorrent/bencode.hpp b/include/libtorrent/bencode.hpp index 1d3f1ea2b..057e3d644 100755 --- a/include/libtorrent/bencode.hpp +++ b/include/libtorrent/bencode.hpp @@ -103,28 +103,35 @@ namespace libtorrent namespace detail { template - 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(); - std::copy(val.begin(), end, out); + int ret = val.length(); + 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); template - 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 // decimal representation of the number can // not hold number bigger than this: BOOST_STATIC_ASSERT(sizeof(entry::integer_type) <= 8); char buf[21]; + int ret = 0; for (char const* str = integer_to_str(buf, 21, val); *str != 0; ++str) { *out = *str; ++out; + ++ret; } + return ret; } template @@ -172,26 +179,31 @@ namespace libtorrent } } + // returns the number of bytes written template - void bencode_recursive(OutIt& out, const entry& e) + int bencode_recursive(OutIt& out, const entry& e) { + int ret = 0; switch(e.type()) { case entry::int_t: write_char(out, 'i'); - write_integer(out, e.integer()); + ret += write_integer(out, e.integer()); write_char(out, 'e'); + ret += 2; break; case entry::string_t: - write_integer(out, e.string().length()); + ret += write_integer(out, e.string().length()); write_char(out, ':'); - write_string(out, e.string()); + ret += write_string(out, e.string()); + ret += 1; break; case entry::list_t: write_char(out, 'l'); 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'); + ret += 2; break; case entry::dictionary_t: write_char(out, 'd'); @@ -199,18 +211,21 @@ namespace libtorrent i != e.dict().end(); ++i) { // write key - write_integer(out, i->first.length()); + ret += write_integer(out, i->first.length()); write_char(out, ':'); - write_string(out, i->first); + ret += write_string(out, i->first); // write value - bencode_recursive(out, i->second); + ret += bencode_recursive(out, i->second); + ret += 1; } write_char(out, 'e'); + ret += 2; break; default: // do nothing break; } + return ret; } template @@ -307,9 +322,9 @@ namespace libtorrent } template - 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 @@ -329,6 +344,25 @@ namespace libtorrent return e; } + template + 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 diff --git a/src/ut_metadata.cpp b/src/ut_metadata.cpp index a6db7ea0c..52badaaea 100644 --- a/src/ut_metadata.cpp +++ b/src/ut_metadata.cpp @@ -255,13 +255,9 @@ namespace libtorrent { namespace // 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); + entry e; + e["msg_type"] = type; + e["piece"] = piece; char const* metadata = 0; int metadata_piece_size = 0; @@ -269,35 +265,29 @@ namespace libtorrent { namespace if (type == 1) { TORRENT_ASSERT(m_pc.associated_torrent().lock()->valid_metadata()); + e["total_size"] = m_tp.metadata().size(); int offset = piece * 16 * 1024; 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(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; + char msg[200]; + char* header = msg; + char* p = &msg[6]; + int len = bencode(p, e); + int total_size = 2 + len + metadata_piece_size; 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); + io::write_uint32(total_size, header); + io::write_uint8(bt_peer_connection::msg_extended, header); + io::write_uint8(m_message_index, header); - 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); + m_pc.send_buffer(msg, len + 6); + if (metadata_piece_size) m_pc.append_send_buffer( + (char*)metadata, metadata_piece_size, &nop); } virtual bool on_extended(int length @@ -311,7 +301,8 @@ namespace libtorrent { namespace 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 piece = msg["piece"].integer(); @@ -343,9 +334,8 @@ namespace libtorrent { namespace 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 + m_tp.received_metadata(body.begin + len, body.left() - len, piece , (total_size && total_size->type() == entry::int_t) ? total_size->integer() : 0); } break;