forked from premiere/premiere-libtorrent
improve interoperability between bdecode_node and entry (for encoding). Make it possible to construct an entry from a bdecode_node. move comparison operators out of entry to support implicit conversions from bdecode_node
This commit is contained in:
parent
295bcc08e5
commit
8841c58435
|
@ -438,6 +438,8 @@ TORRENT_EXPORT int bdecode(char const* start, char const* end, bdecode_node& ret
|
||||||
TORRENT_EXPORT bdecode_node bdecode(span<char const> buffer
|
TORRENT_EXPORT bdecode_node bdecode(span<char const> buffer
|
||||||
, error_code& ec, int* error_pos = nullptr, int depth_limit = 100
|
, error_code& ec, int* error_pos = nullptr, int depth_limit = 100
|
||||||
, int token_limit = 2000000);
|
, int token_limit = 2000000);
|
||||||
|
TORRENT_EXPORT bdecode_node bdecode(span<char const> buffer
|
||||||
|
, int depth_limit = 100, int token_limit = 2000000);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -434,7 +434,6 @@ namespace detail {
|
||||||
if (err) return entry();
|
if (err) return entry();
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
entry bdecode(span<char const> buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TORRENT_BENCODE_HPP_INCLUDED
|
#endif // TORRENT_BENCODE_HPP_INCLUDED
|
||||||
|
|
|
@ -178,16 +178,15 @@ namespace aux {
|
||||||
entry(entry const& e);
|
entry(entry const& e);
|
||||||
entry(entry&& e) noexcept;
|
entry(entry&& e) noexcept;
|
||||||
|
|
||||||
|
// construct from bdecode_node parsed form (see bdecode())
|
||||||
|
entry(bdecode_node const& n); // NOLINT
|
||||||
|
|
||||||
// hidden
|
// hidden
|
||||||
entry();
|
entry();
|
||||||
|
|
||||||
// hidden
|
// hidden
|
||||||
~entry();
|
~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
|
// copies the structure of the right hand side into this
|
||||||
// entry.
|
// entry.
|
||||||
#if TORRENT_ABI_VERSION == 1
|
#if TORRENT_ABI_VERSION == 1
|
||||||
|
@ -340,9 +339,13 @@ namespace aux {
|
||||||
mutable std::uint8_t m_type_queried:1;
|
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 {
|
namespace detail {
|
||||||
|
|
||||||
TORRENT_EXTRA_EXPORT string_view integer_to_str(span<char> buf
|
// internal
|
||||||
|
TORRENT_EXPORT string_view integer_to_str(span<char> buf
|
||||||
, entry::integer_type val);
|
, entry::integer_type val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/bdecode.hpp"
|
#include "libtorrent/bdecode.hpp"
|
||||||
#include "libtorrent/aux_/alloca.hpp"
|
#include "libtorrent/aux_/alloca.hpp"
|
||||||
#include "libtorrent/aux_/numeric_cast.hpp"
|
#include "libtorrent/aux_/numeric_cast.hpp"
|
||||||
|
#include "libtorrent/error_code.hpp"
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <cstring> // for memset
|
#include <cstring> // for memset
|
||||||
#include <cstdio> // for snprintf
|
#include <cstdio> // for snprintf
|
||||||
|
@ -735,6 +736,14 @@ namespace {
|
||||||
return ec ? -1 : 0;
|
return ec ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bdecode_node bdecode(span<char const> 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<char const> buffer
|
bdecode_node bdecode(span<char const> buffer
|
||||||
, error_code& ec, int* error_pos, int depth_limit, int token_limit)
|
, error_code& ec, int* error_pos, int depth_limit, int token_limit)
|
||||||
{
|
{
|
||||||
|
|
|
@ -68,17 +68,6 @@ namespace detail {
|
||||||
}
|
}
|
||||||
} // detail
|
} // detail
|
||||||
|
|
||||||
entry bdecode(span<char const> 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 {
|
namespace {
|
||||||
|
|
||||||
inline void TORRENT_NO_RETURN throw_error()
|
inline void TORRENT_NO_RETURN throw_error()
|
||||||
|
@ -311,6 +300,12 @@ namespace {
|
||||||
this->operator=(std::move(e));
|
this->operator=(std::move(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entry::entry(bdecode_node const& n)
|
||||||
|
: m_type(undefined_t)
|
||||||
|
{
|
||||||
|
this->operator=(n);
|
||||||
|
}
|
||||||
|
|
||||||
entry::entry(dictionary_type v)
|
entry::entry(dictionary_type v)
|
||||||
: m_type(undefined_t)
|
: m_type(undefined_t)
|
||||||
{
|
{
|
||||||
|
@ -494,26 +489,26 @@ namespace {
|
||||||
return *this;
|
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:
|
case entry::int_t:
|
||||||
return integer() == e.integer();
|
return lhs.integer() == rhs.integer();
|
||||||
case string_t:
|
case entry::string_t:
|
||||||
return string() == e.string();
|
return lhs.string() == rhs.string();
|
||||||
case list_t:
|
case entry::list_t:
|
||||||
return list() == e.list();
|
return lhs.list() == rhs.list();
|
||||||
case dictionary_t:
|
case entry::dictionary_t:
|
||||||
return dict() == e.dict();
|
return lhs.dict() == rhs.dict();
|
||||||
case preformatted_t:
|
case entry::preformatted_t:
|
||||||
return preformatted() == e.preformatted();
|
return lhs.preformatted() == rhs.preformatted();
|
||||||
default:
|
case entry::undefined_t:
|
||||||
TORRENT_ASSERT(m_type == undefined_t);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void entry::construct(data_type t)
|
void entry::construct(data_type t)
|
||||||
|
|
|
@ -48,6 +48,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <libtorrent/aux_/vector.hpp>
|
#include <libtorrent/aux_/vector.hpp>
|
||||||
#include <libtorrent/aux_/numeric_cast.hpp>
|
#include <libtorrent/aux_/numeric_cast.hpp>
|
||||||
#include <libtorrent/broadcast_socket.hpp> // for ip_v4
|
#include <libtorrent/broadcast_socket.hpp> // for ip_v4
|
||||||
|
#include <libtorrent/bdecode.hpp>
|
||||||
|
|
||||||
namespace libtorrent { namespace dht {
|
namespace libtorrent { namespace dht {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -355,8 +356,8 @@ namespace {
|
||||||
auto const i = m_immutable_table.find(target);
|
auto const i = m_immutable_table.find(target);
|
||||||
if (i == m_immutable_table.end()) return false;
|
if (i == m_immutable_table.end()) return false;
|
||||||
|
|
||||||
item["v"] = bdecode(i->second.value.get()
|
error_code ec;
|
||||||
, i->second.value.get() + i->second.size);
|
item["v"] = bdecode({i->second.value.get(), i->second.size}, ec);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,7 +413,8 @@ namespace {
|
||||||
item["seq"] = f.seq.value;
|
item["seq"] = f.seq.value;
|
||||||
if (force_fill || (sequence_number(0) <= seq && seq < f.seq))
|
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["sig"] = f.sig.bytes;
|
||||||
item["k"] = f.key.bytes;
|
item["k"] = f.key.bytes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libtorrent/bencode.hpp"
|
#include "libtorrent/bencode.hpp"
|
||||||
|
#include "libtorrent/bdecode.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
@ -56,39 +57,34 @@ std::string encode(entry const& e)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
entry decode(std::string const& str)
|
|
||||||
{
|
|
||||||
return bdecode(str.begin(), str.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
TORRENT_TEST(strings)
|
TORRENT_TEST(strings)
|
||||||
{
|
{
|
||||||
entry e("spam");
|
entry e("spam");
|
||||||
TEST_CHECK(encode(e) == "4:spam");
|
TEST_CHECK(encode(e) == "4:spam");
|
||||||
TEST_CHECK(decode(encode(e)) == e);
|
TEST_CHECK(bdecode(encode(e)) == e);
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_TEST(integers)
|
TORRENT_TEST(integers)
|
||||||
{
|
{
|
||||||
entry e(3);
|
entry e(3);
|
||||||
TEST_CHECK(encode(e) == "i3e");
|
TEST_CHECK(encode(e) == "i3e");
|
||||||
TEST_CHECK(decode(encode(e)) == e);
|
TEST_CHECK(bdecode(encode(e)) == e);
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_TEST(integers2)
|
TORRENT_TEST(integers2)
|
||||||
{
|
{
|
||||||
entry e(-3);
|
entry e(-3);
|
||||||
TEST_CHECK(encode(e) == "i-3e");
|
TEST_CHECK(encode(e) == "i-3e");
|
||||||
TEST_CHECK(decode(encode(e)) == e);
|
TEST_CHECK(bdecode(encode(e)) == e);
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_TEST(integers3)
|
TORRENT_TEST(integers3)
|
||||||
{
|
{
|
||||||
entry e(int(0));
|
entry e(int(0));
|
||||||
TEST_CHECK(encode(e) == "i0e");
|
TEST_CHECK(encode(e) == "i0e");
|
||||||
TEST_CHECK(decode(encode(e)) == e);
|
TEST_CHECK(bdecode(encode(e)) == e);
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_TEST(lists)
|
TORRENT_TEST(lists)
|
||||||
|
@ -98,7 +94,7 @@ TORRENT_TEST(lists)
|
||||||
l.push_back(entry("eggs"));
|
l.push_back(entry("eggs"));
|
||||||
entry e(l);
|
entry e(l);
|
||||||
TEST_CHECK(encode(e) == "l4:spam4:eggse");
|
TEST_CHECK(encode(e) == "l4:spam4:eggse");
|
||||||
TEST_CHECK(decode(encode(e)) == e);
|
TEST_CHECK(bdecode(encode(e)) == e);
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_TEST(dictionaries)
|
TORRENT_TEST(dictionaries)
|
||||||
|
@ -107,7 +103,7 @@ TORRENT_TEST(dictionaries)
|
||||||
e["spam"] = entry("eggs");
|
e["spam"] = entry("eggs");
|
||||||
e["cow"] = entry("moo");
|
e["cow"] = entry("moo");
|
||||||
TEST_CHECK(encode(e) == "d3:cow3:moo4:spam4:eggse");
|
TEST_CHECK(encode(e) == "d3:cow3:moo4:spam4:eggse");
|
||||||
TEST_CHECK(decode(encode(e)) == e);
|
TEST_CHECK(bdecode(encode(e)) == e);
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_TEST(preformatted)
|
TORRENT_TEST(preformatted)
|
||||||
|
@ -620,7 +616,8 @@ TORRENT_TEST(lazy_entry)
|
||||||
|
|
||||||
{
|
{
|
||||||
unsigned char buf[] = { 0x44, 0x91, 0x3a };
|
unsigned char buf[] = { 0x44, 0x91, 0x3a };
|
||||||
entry ent = bdecode(reinterpret_cast<char*>(buf), reinterpret_cast<char*>(buf) + sizeof(buf));
|
error_code ec;
|
||||||
|
entry ent = bdecode({reinterpret_cast<char*>(buf), int(sizeof(buf))}, ec);
|
||||||
TEST_CHECK(ent == entry());
|
TEST_CHECK(ent == entry());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -154,7 +154,7 @@ void print_message(char const* buffer, int len)
|
||||||
else if (msg == 20 && len > 4 && buffer[1] == 0 )
|
else if (msg == 20 && len > 4 && buffer[1] == 0 )
|
||||||
{
|
{
|
||||||
std::snprintf(extra, sizeof(extra), "%s"
|
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];
|
int extmsg = recv_buffer[1];
|
||||||
if (extmsg != 0) continue;
|
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];
|
int extmsg = recv_buffer[1];
|
||||||
if (extmsg != 1) continue;
|
if (extmsg != 1) continue;
|
||||||
|
|
||||||
return bdecode(recv_buffer + 2, recv_buffer + len);
|
return bdecode({recv_buffer + 2, len - 2});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // TORRENT_DISABLE_EXTENSIONS
|
#endif // TORRENT_DISABLE_EXTENSIONS
|
||||||
|
@ -831,7 +831,7 @@ TORRENT_TEST(dont_have)
|
||||||
{
|
{
|
||||||
print_session_log(*ses);
|
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;
|
if (len == -1) break;
|
||||||
print_message(recv_buffer, len);
|
print_message(recv_buffer, len);
|
||||||
if (len == 0) continue;
|
if (len == 0) continue;
|
||||||
|
@ -840,15 +840,15 @@ TORRENT_TEST(dont_have)
|
||||||
int ext_msg = recv_buffer[1];
|
int ext_msg = recv_buffer[1];
|
||||||
if (ext_msg != 0) continue;
|
if (ext_msg != 0) continue;
|
||||||
|
|
||||||
bdecode_node e;
|
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
int ret = bdecode(recv_buffer + 2, recv_buffer + len, e, ec, &pos);
|
ec.clear();
|
||||||
if (ret != 0)
|
bdecode_node e = bdecode({recv_buffer + 2, len - 2}, ec, &pos);
|
||||||
|
if (ec)
|
||||||
{
|
{
|
||||||
log("failed to parse extension handshake: %s at pos %d"
|
log("failed to parse extension handshake: %s at pos %d"
|
||||||
, ec.message().c_str(), pos);
|
, ec.message().c_str(), pos);
|
||||||
}
|
}
|
||||||
TEST_EQUAL(ret, 0);
|
TEST_CHECK(!ec);
|
||||||
|
|
||||||
log("extension handshake: %s", print_entry(e).c_str());
|
log("extension handshake: %s", print_entry(e).c_str());
|
||||||
bdecode_node m = e.dict_find_dict("m");
|
bdecode_node m = e.dict_find_dict("m");
|
||||||
|
|
|
@ -201,7 +201,7 @@ TORRENT_TEST(read_resume_torrent)
|
||||||
rd["file-format"] = "libtorrent resume file";
|
rd["file-format"] = "libtorrent resume file";
|
||||||
rd["file-version"] = 1;
|
rd["file-version"] = 1;
|
||||||
rd["info-hash"] = ti->info_hash().to_string();
|
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<char> resume_data;
|
std::vector<char> resume_data;
|
||||||
bencode(std::back_inserter(resume_data), rd);
|
bencode(std::back_inserter(resume_data), rd);
|
||||||
|
|
|
@ -890,7 +890,7 @@ TORRENT_TEST(backwards_compatible_resume_info_dict)
|
||||||
rd["name"] = ti->name();
|
rd["name"] = ti->name();
|
||||||
rd["info-hash"] = ti->info_hash();
|
rd["info-hash"] = ti->info_hash();
|
||||||
auto metainfo = ti->metadata();
|
auto metainfo = ti->metadata();
|
||||||
rd["info"] = bdecode(metainfo.get(), metainfo.get() + ti->metadata_size());
|
rd["info"] = bdecode({metainfo.get(), ti->metadata_size()});
|
||||||
std::vector<char> resume_data;
|
std::vector<char> resume_data;
|
||||||
bencode(back_inserter(resume_data), rd);
|
bencode(back_inserter(resume_data), rd);
|
||||||
|
|
||||||
|
@ -917,7 +917,7 @@ TORRENT_TEST(resume_info_dict)
|
||||||
rd["name"] = ti->name();
|
rd["name"] = ti->name();
|
||||||
rd["info-hash"] = ti->info_hash();
|
rd["info-hash"] = ti->info_hash();
|
||||||
auto metainfo = ti->metadata();
|
auto metainfo = ti->metadata();
|
||||||
rd["info"] = bdecode(metainfo.get(), metainfo.get() + ti->metadata_size());
|
rd["info"] = bdecode({metainfo.get(), ti->metadata_size()});
|
||||||
std::vector<char> resume_data;
|
std::vector<char> resume_data;
|
||||||
bencode(back_inserter(resume_data), rd);
|
bencode(back_inserter(resume_data), rd);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue