diff --git a/include/libtorrent/bdecode.hpp b/include/libtorrent/bdecode.hpp index bb4f88206..158bee566 100644 --- a/include/libtorrent/bdecode.hpp +++ b/include/libtorrent/bdecode.hpp @@ -438,6 +438,8 @@ TORRENT_EXPORT int bdecode(char const* start, char const* end, bdecode_node& ret TORRENT_EXPORT bdecode_node bdecode(span buffer , error_code& ec, int* error_pos = nullptr, int depth_limit = 100 , int token_limit = 2000000); +TORRENT_EXPORT bdecode_node bdecode(span buffer + , int depth_limit = 100, int token_limit = 2000000); } diff --git a/include/libtorrent/bencode.hpp b/include/libtorrent/bencode.hpp index 57382b761..9c76b8442 100644 --- a/include/libtorrent/bencode.hpp +++ b/include/libtorrent/bencode.hpp @@ -434,7 +434,6 @@ namespace detail { if (err) return entry(); return e; } - entry bdecode(span buffer); } #endif // TORRENT_BENCODE_HPP_INCLUDED diff --git a/include/libtorrent/entry.hpp b/include/libtorrent/entry.hpp index c7d410e42..1a948b392 100644 --- a/include/libtorrent/entry.hpp +++ b/include/libtorrent/entry.hpp @@ -178,16 +178,15 @@ namespace aux { entry(entry const& e); entry(entry&& e) noexcept; + // construct from bdecode_node parsed form (see bdecode()) + entry(bdecode_node const& n); // NOLINT + // hidden entry(); // hidden ~entry(); - // hidden - bool operator==(entry const& e) const; - bool operator!=(entry const& e) const { return !(*this == e); } - // copies the structure of the right hand side into this // entry. #if TORRENT_ABI_VERSION == 1 @@ -340,9 +339,13 @@ namespace aux { mutable std::uint8_t m_type_queried:1; }; + TORRENT_EXPORT bool operator==(entry const& lhs, entry const& rhs); + inline bool operator!=(entry const& lhs, entry const& rhs) { return !(lhs == rhs); } + namespace detail { - TORRENT_EXTRA_EXPORT string_view integer_to_str(span buf + // internal + TORRENT_EXPORT string_view integer_to_str(span buf , entry::integer_type val); } diff --git a/src/bdecode.cpp b/src/bdecode.cpp index 0b90fd442..d728b5421 100644 --- a/src/bdecode.cpp +++ b/src/bdecode.cpp @@ -33,6 +33,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/bdecode.hpp" #include "libtorrent/aux_/alloca.hpp" #include "libtorrent/aux_/numeric_cast.hpp" +#include "libtorrent/error_code.hpp" #include #include // for memset #include // for snprintf @@ -735,6 +736,14 @@ namespace { return ec ? -1 : 0; } + bdecode_node bdecode(span buffer, int depth_limit, int token_limit) + { + error_code ec; + bdecode_node ret = bdecode(buffer, ec, nullptr, depth_limit, token_limit); + if (ec) throw system_error(ec); + return ret; + } + bdecode_node bdecode(span buffer , error_code& ec, int* error_pos, int depth_limit, int token_limit) { diff --git a/src/entry.cpp b/src/entry.cpp index 23a81c721..6ed3b3c49 100644 --- a/src/entry.cpp +++ b/src/entry.cpp @@ -68,17 +68,6 @@ namespace detail { } } // detail - entry bdecode(span buffer) - { - entry e; - bool err = false; - auto it = buffer.begin(); - detail::bdecode_recursive(it, buffer.end(), e, err, 0); - TORRENT_ASSERT(e.m_type_queried == false); - if (err) return entry(); - return e; - } - namespace { inline void TORRENT_NO_RETURN throw_error() @@ -311,6 +300,12 @@ namespace { this->operator=(std::move(e)); } + entry::entry(bdecode_node const& n) + : m_type(undefined_t) + { + this->operator=(n); + } + entry::entry(dictionary_type v) : m_type(undefined_t) { @@ -494,26 +489,26 @@ namespace { return *this; } - bool entry::operator==(entry const& e) const + bool operator==(entry const& lhs, entry const& rhs) { - if (type() != e.type()) return false; + if (lhs.type() != rhs.type()) return false; - switch (m_type) + switch (lhs.type()) { - case int_t: - return integer() == e.integer(); - case string_t: - return string() == e.string(); - case list_t: - return list() == e.list(); - case dictionary_t: - return dict() == e.dict(); - case preformatted_t: - return preformatted() == e.preformatted(); - default: - TORRENT_ASSERT(m_type == undefined_t); + case entry::int_t: + return lhs.integer() == rhs.integer(); + case entry::string_t: + return lhs.string() == rhs.string(); + case entry::list_t: + return lhs.list() == rhs.list(); + case entry::dictionary_t: + return lhs.dict() == rhs.dict(); + case entry::preformatted_t: + return lhs.preformatted() == rhs.preformatted(); + case entry::undefined_t: return true; } + return false; } void entry::construct(data_type t) diff --git a/src/kademlia/dht_storage.cpp b/src/kademlia/dht_storage.cpp index 6fd2f5ab9..7def4b175 100644 --- a/src/kademlia/dht_storage.cpp +++ b/src/kademlia/dht_storage.cpp @@ -48,6 +48,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include // for ip_v4 +#include namespace libtorrent { namespace dht { namespace { @@ -355,8 +356,8 @@ namespace { auto const i = m_immutable_table.find(target); if (i == m_immutable_table.end()) return false; - item["v"] = bdecode(i->second.value.get() - , i->second.value.get() + i->second.size); + error_code ec; + item["v"] = bdecode({i->second.value.get(), i->second.size}, ec); return true; } @@ -412,7 +413,8 @@ namespace { item["seq"] = f.seq.value; if (force_fill || (sequence_number(0) <= seq && seq < f.seq)) { - item["v"] = bdecode(f.value.get(), f.value.get() + f.size); + error_code ec; + item["v"] = bdecode({f.value.get(), f.size}, ec); item["sig"] = f.sig.bytes; item["k"] = f.key.bytes; } diff --git a/test/test_bencoding.cpp b/test/test_bencoding.cpp index 6814dac3c..fb6173325 100644 --- a/test/test_bencoding.cpp +++ b/test/test_bencoding.cpp @@ -31,6 +31,7 @@ POSSIBILITY OF SUCH DAMAGE. */ #include "libtorrent/bencode.hpp" +#include "libtorrent/bdecode.hpp" #include #include @@ -56,39 +57,34 @@ std::string encode(entry const& e) return ret; } -entry decode(std::string const& str) -{ - return bdecode(str.begin(), str.end()); -} - } // anonymous namespace TORRENT_TEST(strings) { entry e("spam"); TEST_CHECK(encode(e) == "4:spam"); - TEST_CHECK(decode(encode(e)) == e); + TEST_CHECK(bdecode(encode(e)) == e); } TORRENT_TEST(integers) { entry e(3); TEST_CHECK(encode(e) == "i3e"); - TEST_CHECK(decode(encode(e)) == e); + TEST_CHECK(bdecode(encode(e)) == e); } TORRENT_TEST(integers2) { entry e(-3); TEST_CHECK(encode(e) == "i-3e"); - TEST_CHECK(decode(encode(e)) == e); + TEST_CHECK(bdecode(encode(e)) == e); } TORRENT_TEST(integers3) { entry e(int(0)); TEST_CHECK(encode(e) == "i0e"); - TEST_CHECK(decode(encode(e)) == e); + TEST_CHECK(bdecode(encode(e)) == e); } TORRENT_TEST(lists) @@ -98,7 +94,7 @@ TORRENT_TEST(lists) l.push_back(entry("eggs")); entry e(l); TEST_CHECK(encode(e) == "l4:spam4:eggse"); - TEST_CHECK(decode(encode(e)) == e); + TEST_CHECK(bdecode(encode(e)) == e); } TORRENT_TEST(dictionaries) @@ -107,7 +103,7 @@ TORRENT_TEST(dictionaries) e["spam"] = entry("eggs"); e["cow"] = entry("moo"); TEST_CHECK(encode(e) == "d3:cow3:moo4:spam4:eggse"); - TEST_CHECK(decode(encode(e)) == e); + TEST_CHECK(bdecode(encode(e)) == e); } TORRENT_TEST(preformatted) @@ -620,7 +616,8 @@ TORRENT_TEST(lazy_entry) { unsigned char buf[] = { 0x44, 0x91, 0x3a }; - entry ent = bdecode(reinterpret_cast(buf), reinterpret_cast(buf) + sizeof(buf)); + error_code ec; + entry ent = bdecode({reinterpret_cast(buf), int(sizeof(buf))}, ec); TEST_CHECK(ent == entry()); } diff --git a/test/test_fast_extension.cpp b/test/test_fast_extension.cpp index ded7f6730..17081d8e9 100644 --- a/test/test_fast_extension.cpp +++ b/test/test_fast_extension.cpp @@ -154,7 +154,7 @@ void print_message(char const* buffer, int len) else if (msg == 20 && len > 4 && buffer[1] == 0 ) { std::snprintf(extra, sizeof(extra), "%s" - , bdecode(buffer + 2, buffer + len).to_string().c_str()); + , print_entry(bdecode({buffer + 2, len - 2})).c_str()); } } @@ -356,7 +356,7 @@ entry read_extension_handshake(tcp::socket& s, char* recv_buffer, int size) int extmsg = recv_buffer[1]; if (extmsg != 0) continue; - return bdecode(recv_buffer + 2, recv_buffer + len); + return bdecode({recv_buffer + 2, len - 2}); } } @@ -409,7 +409,7 @@ entry read_ut_metadata_msg(tcp::socket& s, char* recv_buffer, int size) int extmsg = recv_buffer[1]; if (extmsg != 1) continue; - return bdecode(recv_buffer + 2, recv_buffer + len); + return bdecode({recv_buffer + 2, len - 2}); } } #endif // TORRENT_DISABLE_EXTENSIONS @@ -831,7 +831,7 @@ TORRENT_TEST(dont_have) { print_session_log(*ses); - int len = read_message(s, recv_buffer, sizeof(recv_buffer)); + int const len = read_message(s, recv_buffer, sizeof(recv_buffer)); if (len == -1) break; print_message(recv_buffer, len); if (len == 0) continue; @@ -840,15 +840,15 @@ TORRENT_TEST(dont_have) int ext_msg = recv_buffer[1]; if (ext_msg != 0) continue; - bdecode_node e; int pos = 0; - int ret = bdecode(recv_buffer + 2, recv_buffer + len, e, ec, &pos); - if (ret != 0) + ec.clear(); + bdecode_node e = bdecode({recv_buffer + 2, len - 2}, ec, &pos); + if (ec) { log("failed to parse extension handshake: %s at pos %d" , ec.message().c_str(), pos); } - TEST_EQUAL(ret, 0); + TEST_CHECK(!ec); log("extension handshake: %s", print_entry(e).c_str()); bdecode_node m = e.dict_find_dict("m"); diff --git a/test/test_read_resume.cpp b/test/test_read_resume.cpp index 5cac08ff5..082a75ece 100644 --- a/test/test_read_resume.cpp +++ b/test/test_read_resume.cpp @@ -201,7 +201,7 @@ TORRENT_TEST(read_resume_torrent) rd["file-format"] = "libtorrent resume file"; rd["file-version"] = 1; rd["info-hash"] = ti->info_hash().to_string(); - rd["info"] = bdecode(ti->metadata().get(), ti->metadata().get() + ti->metadata_size()); + rd["info"] = bdecode({ti->metadata().get(), ti->metadata_size()}); std::vector resume_data; bencode(std::back_inserter(resume_data), rd); diff --git a/test/test_resume.cpp b/test/test_resume.cpp index 0c92e3fa7..dbcd7e32d 100644 --- a/test/test_resume.cpp +++ b/test/test_resume.cpp @@ -890,7 +890,7 @@ TORRENT_TEST(backwards_compatible_resume_info_dict) rd["name"] = ti->name(); rd["info-hash"] = ti->info_hash(); auto metainfo = ti->metadata(); - rd["info"] = bdecode(metainfo.get(), metainfo.get() + ti->metadata_size()); + rd["info"] = bdecode({metainfo.get(), ti->metadata_size()}); std::vector resume_data; bencode(back_inserter(resume_data), rd); @@ -917,7 +917,7 @@ TORRENT_TEST(resume_info_dict) rd["name"] = ti->name(); rd["info-hash"] = ti->info_hash(); auto metainfo = ti->metadata(); - rd["info"] = bdecode(metainfo.get(), metainfo.get() + ti->metadata_size()); + rd["info"] = bdecode({metainfo.get(), ti->metadata_size()}); std::vector resume_data; bencode(back_inserter(resume_data), rd);