landed the bdecode branch in master. lazy_bdecode/lazy_entry is now being replaced by bdecode/bdecode_node

This commit is contained in:
Arvid Norberg 2015-03-12 05:20:12 +00:00
parent c1dc982f4f
commit 6c1df7eb55
72 changed files with 4039 additions and 1144 deletions

View File

@ -13,6 +13,7 @@ set(sources
bandwidth_limit
bandwidth_manager
bandwidth_queue_entry
bdecode
block_cache
bloom_filter
chained_buffer

View File

@ -1,3 +1,4 @@
* replaced lazy_bdecode with a new bdecoder that's a lot more efficient
* deprecate time functions, expose typedefs of boost::chrono in the libtorrent
namespace instead
* deprecate file_base feature in file_storage/torrent_info

View File

@ -529,6 +529,7 @@ SOURCES =
bandwidth_limit
bandwidth_manager
bandwidth_queue_entry
bdecode
block_cache
bloom_filter
chained_buffer

View File

@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/python.hpp>
#include <libtorrent/error_code.hpp>
#include <libtorrent/lazy_entry.hpp>
#include <libtorrent/bdecode.hpp>
#include <libtorrent/upnp.hpp>
#include <libtorrent/socks5_stream.hpp>

View File

@ -12,7 +12,7 @@
#include <libtorrent/disk_io_thread.hpp>
#include <libtorrent/aux_/session_settings.hpp>
#include <libtorrent/extensions.hpp>
#include <libtorrent/lazy_entry.hpp>
#include <libtorrent/bdecode.hpp>
#include <libtorrent/bencode.hpp>
#include <libtorrent/aux_/session_impl.hpp> // for settings_map()
@ -486,9 +486,9 @@ namespace
std::vector<char> buf;
bencode(std::back_inserter(buf), st);
lazy_entry e;
bdecode_node e;
error_code ec;
lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec);
bdecode(&buf[0], &buf[0] + buf.size(), e, ec);
TORRENT_ASSERT(!ec);
ses.load_state(e);
}

View File

@ -82,6 +82,7 @@ category_mapping = {
'alert_types.hpp': 'Alerts',
'bencode.hpp': 'Bencoding',
'lazy_entry.hpp': 'Bencoding',
'bdecode.hpp': 'Bdecoding',
'entry.hpp': 'Bencoding',
'time.hpp': 'Time',
'escape_string.hpp': 'String',

View File

@ -85,8 +85,8 @@ $(REFERENCE_TARGETS:=.rst):gen_reference_doc.py ../include/libtorrent/*.hpp ../i
rst2pdf $? -o $@ --stylesheets stylesheet
%.html:%.rst
rst2html-2.6.py --template=template.txt --stylesheet-path=style.css --link-stylesheet --no-toc-backlinks $? > $@
rst2html-2.6.py --template=template2.txt --stylesheet-path=style.css --link-stylesheet --no-toc-backlinks $? > $(WEB_PATH)/$@
rst2html-3.4.py --template=template.txt --stylesheet-path=style.css --link-stylesheet --no-toc-backlinks $? > $@
rst2html-3.4.py --template=template2.txt --stylesheet-path=style.css --link-stylesheet --no-toc-backlinks $? > $(WEB_PATH)/$@
%.png:%.dot
dot -Tpng $? >$@

View File

@ -64,7 +64,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/magnet_uri.hpp"
#include "libtorrent/bitfield.hpp"
#include "libtorrent/peer_info.hpp"
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/bdecode.hpp"
#include "libtorrent/add_torrent_params.hpp"
#include "libtorrent/time.hpp"
#include "libtorrent/create_torrent.hpp"
@ -697,7 +697,6 @@ void add_torrent(libtorrent::session& ses
if (seed_mode) p.flags |= add_torrent_params::flag_seed_mode;
if (disable_storage) p.storage = disabled_storage_constructor;
if (share_mode) p.flags |= add_torrent_params::flag_share_mode;
lazy_entry resume_data;
std::string filename = path_append(save_path, path_append(".resume"
, leaf_path(torrent) + ".resume"));
@ -1324,8 +1323,8 @@ int main(int argc, char* argv[])
error_code ec;
if (load_file(".ses_state", in, ec) == 0)
{
lazy_entry e;
if (lazy_bdecode(&in[0], &in[0] + in.size(), e, ec) == 0)
bdecode_node e;
if (bdecode(&in[0], &in[0] + in.size(), e, ec) == 0)
ses.load_state(e);
}

View File

@ -33,10 +33,11 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent_info.hpp"
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/bdecode.hpp"
#include "libtorrent/magnet_uri.hpp"
int load_file(std::string const& filename, std::vector<char>& v, libtorrent::error_code& ec, int limit = 8000000)
int load_file(std::string const& filename, std::vector<char>& v
, libtorrent::error_code& ec, int limit = 8000000)
{
ec.clear();
FILE* f = fopen(filename.c_str(), "rb");
@ -127,11 +128,11 @@ int main(int argc, char* argv[])
fprintf(stderr, "failed to load file: %s\n", ec.message().c_str());
return 1;
}
lazy_entry e;
bdecode_node e;
int pos = -1;
printf("decoding. recursion limit: %d total item count limit: %d\n"
, depth_limit, item_limit);
ret = lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec, &pos
ret = bdecode(&buf[0], &buf[0] + buf.size(), e, ec, &pos
, depth_limit, item_limit);
printf("\n\n----- raw info -----\n\n%s\n", print_entry(e).c_str());

View File

@ -179,8 +179,8 @@ int main(int argc, char* argv[])
error_code ec;
if (load_file(".ses_state", in, ec) == 0)
{
lazy_entry e;
if (lazy_bdecode(&in[0], &in[0] + in.size(), e, ec) == 0)
bdecode_node e;
if (bdecode(&in[0], &in[0] + in.size(), e, ec) == 0)
ses.load_state(e);
}

View File

@ -16,6 +16,7 @@ nobase_include_HEADERS = \
bandwidth_socket.hpp \
bandwidth_queue_entry.hpp \
bencode.hpp \
bdecode.hpp \
bitfield.hpp \
block_cache.hpp \
bloom_filter.hpp \

View File

@ -492,7 +492,7 @@ namespace libtorrent
void announce_lsd(sha1_hash const& ih, int port, bool broadcast = false);
void save_state(entry* e, boost::uint32_t flags) const;
void load_state(lazy_entry const* e);
void load_state(bdecode_node const* e);
bool has_connection(peer_connection* p) const;
void insert_peer(boost::shared_ptr<peer_connection> const& c);

View File

@ -0,0 +1,409 @@
/*
Copyright (c) 2015, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <boost/cstdint.hpp>
#include <boost/system/error_code.hpp>
#include <vector>
#include <string>
#include "libtorrent/assert.hpp"
#ifndef TORRENT_BDECODE_HPP
#define TORRENT_BDECODE_HPP
/*
This is an efficient bdecoder. It decodes into a flat memory buffer of tokens.
Each token has an offset into the bencoded buffer where the token came from
and a next pointer, which is a relative number of tokens to skip forward to
get to the logical next item in a container.
strings and ints offset pointers point to the first character of the length
prefix or the 'i' character. This is to maintain uniformity with other types
and to allow easily calculating the span of a node by subtracting its offset
by the offset of the next node.
example layout:
{
"a": { "b": 1, "c": "abcd" },
"d": 3
}
/---------------------------------------------------------------------------------------\
| |
| |
| /--------------------------------------------\ |
| | | |
| | | |
| /-----\ | /----\ /----\ /----\ /----\ | /----\ /----\ |
| next | | | | | | | | | | | | | | | | |
| pointers | v | | v | v | v | v v | v | v v
+-+-----+----+--+----+--+----+--+----+--+----+--+----+--+-------+----+--+----+--+------+ X
| dict | str | dict | str | int | str | str | end | str | int | end |
| | | | | | | | | | | |
| | | | | | | | | | | |
+-+-----+-+-----+-+-----+-+-----+-+-----+-+-----+-+-----+-+-----+-+-----+-+-----+-+----+
| offset| | | | | | | | | |
| | | | | | | | | | |
|/------/ | | | | | | | | |
|| /-----------/ | | | | | | | |
|| |/------------------/ | | | | | | |
|| || /-----------------------/ | | | | | |
|| || | /----------------------------/ | | | | |
|| || | | /---------------------------------/ | | | |
|| || | | | /-----------------------------------/ | | |
|| || | | | |/------------------------------------------/ | |
|| || | | | || /-----------------------------------------------/ |
|| || | | | || | /----------------------------------------------------/
|| || | | | || | |
vv vv v v v vv v v
``d1:ad1:bi1e1:c4:abcde1:di3ee``
*/
namespace libtorrent {
TORRENT_EXPORT boost::system::error_category& get_bdecode_category();
namespace bdecode_errors
{
// libtorrent uses boost.system's ``error_code`` class to represent
// errors. libtorrent has its own error category get_bdecode_category()
// whith the error codes defined by error_code_enum.
enum error_code_enum
{
// Not an error
no_error = 0,
// expected string in bencoded string
expected_digit,
// expected colon in bencoded string
expected_colon,
// unexpected end of file in bencoded string
unexpected_eof,
// expected value (list, dict, int or string) in bencoded string
expected_value,
// bencoded recursion depth limit exceeded
depth_exceeded,
// bencoded item count limit exceeded
limit_exceeded,
// integer overflow
overflow,
// the number of error codes
error_code_max
};
// hidden
TORRENT_EXPORT boost::system::error_code make_error_code(error_code_enum e);
}
} // namespace libtorrent
namespace boost { namespace system {
template<> struct is_error_code_enum<libtorrent::bdecode_errors::error_code_enum>
{ static const bool value = true; };
template<> struct is_error_condition_enum<libtorrent::bdecode_errors::error_code_enum>
{ static const bool value = true; };
} }
namespace libtorrent {
typedef boost::system::error_code error_code;
TORRENT_EXTRA_EXPORT char const* parse_int(char const* start
, char const* end, char delimiter, boost::int64_t& val
, bdecode_errors::error_code_enum& ec);
namespace detail
{
// internal
struct bdecode_token
{
// the node with type 'end' is a logical node, pointing to the end
// of the bencoded buffer.
enum type_t
{ none, dict, list, string, integer, end };
enum limits_t
{
max_offset = (1 << 29) - 1,
max_next_item = (1 << 29) - 1,
max_header = (1 << 3) - 1,
};
bdecode_token(boost::uint32_t off, bdecode_token::type_t t)
: offset(off)
, type(t)
, next_item(0)
, header(0)
{
TORRENT_ASSERT(off <= max_offset);
TORRENT_ASSERT(t >= 0 && t <= end);
}
bdecode_token(boost::uint32_t off, boost::uint32_t next
, bdecode_token::type_t t, boost::uint8_t header_size = 0)
: offset(off)
, type(t)
, next_item(next)
, header(type == string ? header_size - 2 : 0)
{
TORRENT_ASSERT(type != string || header_size >= 2);
TORRENT_ASSERT(off <= max_offset);
TORRENT_ASSERT(next <= max_next_item);
TORRENT_ASSERT(header_size < 8);
TORRENT_ASSERT(t >= 0 && t <= end);
}
int start_offset() const { TORRENT_ASSERT(type == string); return header + 2; }
// offset into the bdecoded buffer where this node is
boost::uint32_t offset:29;
// one of type_t enums
boost::uint32_t type:3;
// if this node is a member of a list, 'next_item' is the number of nodes
// to jump forward in th node array to get to the next item in the list.
// if it's a key in a dictionary, it's the number of step forwards to get
// to its corresponding value. If it's a value in a dictionary, it's the
// number of steps to the next key, or to the end node.
// this is the _relative_ offset to the next node
boost::uint32_t next_item:29;
// this is the number of bytes to skip forward from the offset to get to the
// first character of the string, if this is a string. This field is not
// used for other types. Essentially this is the length of the length prefix
// and the colon. Since a string always has at least one character of length
// prefix and always a colon, those 2 characters are implied.
boost::uint32_t header:3;
};
}
// a ``bdecode_node`` is used to traverse and hold the tree structure defined
// by bencoded data after it has been parse by bdecode().
//
// There are primarily two kinds of bdecode_nodes. The ones that own the tree
// structure, and defines its lifetime, and nodes that are child nodes in the
// tree, pointing back into the root's tree.
//
// The ``bdecode_node`` passed in to ``bdecode()`` becomes the one owning the
// tree structure. Make sure not to destruct that object for as long as you
// use any of its child nodes. Also, keep in mind that the buffer originally
// parsed also must remain valid while using it. (see switch_underlying_buffer()).
//
// Copying an owning node will create a copy of the whole tree, but will still
// point into the same parsed bencoded buffer as the first one.
// Sometimes it's important to get a non-owning reference to the root node (
// to be able to copy it as a reference for instance). For that, use the
// non_owninig() member function.
//
// There are 5 different types of nodes, see type_t.
struct TORRENT_EXPORT bdecode_node
{
friend int bdecode(char const* start, char const* end, bdecode_node& ret
, error_code& ec, int* error_pos, int depth_limit, int token_limit);
// creates a default constructed node, it will have the type ``none_t``.
bdecode_node();
// For owning nodes, the copy will create a copy of the tree, but the
// underlying buffer remains the same.
bdecode_node(bdecode_node const&);
bdecode_node& operator=(bdecode_node const&);
// the dypes of bdecoded nodes
enum type_t
{
// uninitialized or default constructed. This is also used
// to indicate that a node was not found in some cases.
none_t,
// a dictionary node. The ``dict_find_`` functions are valid.
dict_t,
// a list node. The ``list_`` functions are valid.
list_t,
// a string node, the ``string_`` functions are valid.
string_t,
// an integer node. The ``int_`` functions are valid.
int_t
};
// the type of this node. See type_t.
type_t type() const;
// returns true if type() != none_t.
operator bool() const;
// return a non-owning reference to this node. This is useful to refer to
// the root node without copying it in assignments.
bdecode_node non_owning() const;
// returns the buffer and length of the section in the original bencoded
// buffer where this node is defined. For a dictionary for instance, this
// starts with ``d`` and ends with ``e``, and has all the content of the
// dictionary in between.
std::pair<char const*, int> data_section() const;
// functions with the ``list_`` prefix operate on lists. These functions are
// only valid if ``type()`` == ``list_t``. ``list_at()`` returns the item
// in the list at index ``i``. ``i`` may not be greater than or equal to the
// size of the list. ``size()`` returns the size of the list.
bdecode_node list_at(int i) const;
std::string list_string_value_at(int i
, char const* default_val = "");
boost::int64_t list_int_value_at(int i
, boost::int64_t default_val = 0);
int list_size() const;
// functions with the ``dict_`` prefix operates on dictionaries. Theu are
// only valid if ``type()`` == ``dict_t``. In case a key you're looking up
// contains a 0 byte, you cannot use the null-terminated string overloads,
// but have to use ``std::string`` instead. ``dict_find_list`` will return
// a valid ``bdecode_node`` if the key is found _and_ it is a list. Otherwise
// it will return a default-constructed bdecode_node.
bdecode_node dict_find(std::string key) const;
bdecode_node dict_find(char const* key) const;
std::pair<std::string, bdecode_node> dict_at(int i) const;
bdecode_node dict_find_dict(std::string key) const;
bdecode_node dict_find_dict(char const* key) const;
bdecode_node dict_find_list(char const* key) const;
bdecode_node dict_find_string(char const* key) const;
bdecode_node dict_find_int(char const* key) const;
std::string dict_find_string_value(char const* key
, char const* default_value = "") const;
boost::int64_t dict_find_int_value(char const* key
, boost::int64_t default_val = 0) const;
int dict_size() const;
// this function is only valid if ``type()`` == ``int_t``. It returns the
// value of the integer.
boost::int64_t int_value() const;
// these functions are only valid if ``type()`` == ``string_t``. They return
// the string values. Note that ``string_ptr()`` is _not_ null-terminated.
// ``string_length()`` returns the number of bytes in the string.
std::string string_value() const;
char const* string_ptr() const;
int string_length() const;
// resets the ``bdecoded_node`` to a default constructed state. If this is
// an owning node, the tree is freed and all child nodes are invalidated.
void clear();
// Swap contents.
void swap(bdecode_node& n);
// pre-allocate memory for the specified numbers of tokens. This is
// useful if you know approximately how many tokens are in the file
// you are about to parse. Doing so will save realloc operations
// while parsing. You should only call this on the root node, before
// passing it in to bdecode().
void reserve(int tokens);
// this buffer MUST be identical to the one originally parsed.
// This operation is only defined on owning root nodes, i.e. the one
// passed in to decode().
void switch_underlying_buffer(char const* buf);
private:
bdecode_node(detail::bdecode_token const* tokens, char const* buf
, int len, int idx);
// if this is the root node, that owns all the tokens, they live in this
// vector. If this is a sub-node, this field is not used, instead the
// m_root_tokens pointer points to the root node's token.
std::vector<detail::bdecode_token> m_tokens;
// this points to the root nodes token vector
// for the root node, this points to its own m_tokens member
detail::bdecode_token const* m_root_tokens;
// this points to the original buffer that was parsed
char const* m_buffer;
int m_buffer_size;
// this is the index into m_root_tokens that this node refers to
// for the root node, it's 0. -1 means uninitialized.
int m_token_idx;
// this is a cache of the last element index looked up. This only applies
// to lists and dictionaries. If the next lookup is at m_last_index or
// greater, we can start iterating the tokens at m_last_token.
mutable int m_last_index;
mutable int m_last_token;
// the number of elements in this list or dict (computed on the first
// call to dict_size() or list_size())
mutable int m_size;
};
// print the bencoded structure in a human-readable format to a string
// that's returned.
TORRENT_EXPORT std::string print_entry(bdecode_node const& e
, bool single_line = false, int indent = 0);
// This function decodes/parses bdecoded data (for example a .torrent file).
// The data structure is returned in the ``ret`` argument.
// the buffer to parse is specified by the ``start`` of the buffer as well as
// the ``end``, i.e. one byte past the end. If the buffer fails to parse, the
// function returns a non-zero value and fills in ``ec`` with the error code.
// The optional argument ``error_pos``, if set to non-null, will be set to the byte
// offset into the buffer where the parse failure occurred.
//
// ``depth_limit`` specifies the max number of nested lists or dictionaries are
// allowed in the data structure. (This affects the stack usage of the
// function, be careful not to set it too high).
//
// ``token_limit`` is the max number of tokens allowed to be parsed from the
// buffer. This is simply a sanity check to not have unbounded memory usage.
//
// The resulting ``bdecode_node`` is an *owning* node. That means it will
// be holding the whole parsed tree. When iterating lists and dictionaries,
// those ``bdecode_node``s will simply have references to the root or owning
// ``bdecode_node``. If the root node is destructed, all other nodes that
// refer to anything in that tree become invalid.
//
// However, the underlying buffer passed in to this function (``start``, ``end``)
// must also remain valid while the bdecoded tree is used. The parsed tree
// produced by this function does not copy any data out of the buffer, but
// simply produces references back into it.
TORRENT_EXPORT int bdecode(char const* start, char const* end, bdecode_node& ret
, error_code& ec, int* error_pos = 0, int depth_limit = 100
, int token_limit = 1000000);
}
#endif // TORRENT_BDECODE_HPP

View File

@ -51,7 +51,7 @@ POSSIBILITY OF SUCH DAMAGE.
//
// There are two mechanims to *decode* bencoded buffers in libtorrent.
//
// The most flexible one is bdecode(), which returns a structure
// The most flexible one is `bdecode() bencode()`_, which returns a structure
// represented by entry. When a buffer is decoded with this function,
// it can be discarded. The entry does not contain any references back
// to it. This means that bdecode() actually copies all the data out
@ -59,16 +59,16 @@ POSSIBILITY OF SUCH DAMAGE.
// function potentially expensive, if you're parsing large amounts
// of data.
//
// Another consideration is that bdecode() is a recursive parser.
// Another consideration is that `bdecode() bencode()`_ is a recursive parser.
// For this reason, in order to avoid DoS attacks by triggering
// a stack overflow, there is a recursion limit. This limit is
// a sanity check to make sure it doesn't run the risk of
// busting the stack.
//
// The second mechanism is lazy_bdecode(), which returns a
// bencoded structure represented by lazy_entry. This function
// The second mechanism is bdecode(), which returns a
// bencoded structure represented by bdecode_node. This function
// builds a tree that points back into the original buffer.
// The returned lazy_entry will not be valid once the buffer
// The returned bdecode_node will not be valid once the buffer
// it was parsed out of is discarded.
//
// Not only is this function more efficient because of less
@ -391,9 +391,10 @@ namespace libtorrent
}
}
// These functions will encode data to bencoded_ or decode bencoded_ data.
// These functions will encode data to bencoded or decode bencoded data.
//
// If possible, lazy_bdecode() should be preferred over ``bdecode()``.
// If possible, bdecode() and bdecode_node should be preferred over this
// function.
//
// The entry_ class is the internal representation of the bencoded data
// and it can be used to retrieve information, an entry_ can also be build by

View File

@ -43,6 +43,7 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent
{
// internal
inline void cpuid(unsigned int info[4], int type)
{
#if TORRENT_HAS_SSE && defined _MSC_VER

View File

@ -36,7 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/function/function1.hpp>
#include <boost/shared_ptr.hpp>
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/bdecode.hpp"
#include <string>
@ -66,7 +66,7 @@ namespace libtorrent
, boost::function<void(disk_io_job const*)> const& handler
= boost::function<void(disk_io_job const*)>()) = 0;
virtual void async_check_fastresume(piece_manager* storage
, lazy_entry const* resume_data
, bdecode_node const* resume_data
, boost::function<void(disk_io_job const*)> const& handler) = 0;
#ifndef TORRENT_NO_DEPRECATE
virtual void async_finalize_file(piece_manager*, int file

View File

@ -307,7 +307,7 @@ namespace libtorrent
void async_delete_files(piece_manager* storage
, boost::function<void(disk_io_job const*)> const& handler);
void async_check_fastresume(piece_manager* storage
, lazy_entry const* resume_data
, bdecode_node const* resume_data
, boost::function<void(disk_io_job const*)> const& handler);
void async_save_resume_data(piece_manager* storage
, boost::function<void(disk_io_job const*)> const& handler);

View File

@ -76,7 +76,10 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent
{
#ifndef TORRENT_NO_DEPRECATE
struct lazy_entry;
#endif
struct bdecode_node;
// thrown by any accessor function of entry if the accessor
// function requires a type different than the actual type
@ -142,7 +145,10 @@ namespace libtorrent
// copies the structure of the right hand side into this
// entry.
#ifndef TORRENT_NO_DEPRECATE
void operator=(lazy_entry const&);
#endif
void operator=(bdecode_node const&);
void operator=(entry const&);
void operator=(dictionary_type const&);
void operator=(string_type const&);

View File

@ -191,7 +191,7 @@ namespace libtorrent
struct peer_request;
class peer_connection;
class entry;
struct lazy_entry;
struct bdecode_node;
struct disk_buffer_holder;
struct bitfield;
class alert;
@ -248,7 +248,7 @@ namespace libtorrent
virtual void save_state(entry&) const {}
// called when loading settings state
virtual void load_state(lazy_entry const&) {}
virtual void load_state(bdecode_node const&) {}
};
// Torrent plugins are associated with a single torrent and have a number
@ -387,7 +387,7 @@ namespace libtorrent
// supported by this peer. It will result in this peer_plugin
// being removed from the peer_connection and destructed.
// this is not called for web seeds
virtual bool on_extension_handshake(lazy_entry const&) { return true; }
virtual bool on_extension_handshake(bdecode_node const&) { return true; }
// returning true from any of the message handlers
// indicates that the plugin has handeled the message.

View File

@ -56,7 +56,6 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent
{
namespace aux { struct session_impl; }
struct lazy_entry;
struct counters;
#ifndef TORRENT_NO_DEPRECATE
struct session_status;
@ -139,6 +138,11 @@ namespace libtorrent { namespace dht
virtual bool send_packet(libtorrent::entry& e, udp::endpoint const& addr
, int send_flags);
// this is the bdecode_node DHT messages are parsed into. It's a member
// in order to avoid having to deallocate and re-allocate it for every
// message.
bdecode_node m_msg;
counters& m_counters;
node_impl m_dht;
rate_limited_udp_socket& m_sock;

View File

@ -45,7 +45,7 @@ class get_item : public find_data
public:
typedef boost::function<bool(item&)> data_callback;
void got_data(lazy_entry const* v,
void got_data(bdecode_node const& v,
char const* pk,
boost::uint64_t seq,
char const* sig);

View File

@ -34,7 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
#define LIBTORRENT_ITEM_HPP
#include <libtorrent/sha1_hash.hpp>
#include <libtorrent/lazy_entry.hpp>
#include <libtorrent/bdecode.hpp>
#include <libtorrent/entry.hpp>
#include <vector>
#include <exception>
@ -91,7 +91,7 @@ public:
item(entry const& v
, std::pair<char const*, int> salt
, boost::uint64_t seq, char const* pk, char const* sk);
item(lazy_entry const* v) { assign(v); }
item(bdecode_node const& v) { assign(v); }
void assign(entry const& v)
{
@ -100,12 +100,12 @@ public:
}
void assign(entry const& v, std::pair<char const*, int> salt
, boost::uint64_t seq, char const* pk, char const* sk);
void assign(lazy_entry const* v)
void assign(bdecode_node const& v)
{
assign(v, std::pair<char const*, int>(static_cast<char const*>(NULL)
, 0), 0, NULL, NULL);
}
bool assign(lazy_entry const* v, std::pair<char const*, int> salt
bool assign(bdecode_node const& v, std::pair<char const*, int> salt
, boost::uint64_t seq, char const* pk, char const* sig);
void assign(entry const& v, std::string salt, boost::uint64_t seq
, char const* pk, char const* sig);

View File

@ -51,9 +51,9 @@ typedef std::vector<tcp::endpoint> peers_t;
struct msg
{
msg(lazy_entry const& m, udp::endpoint const& ep): message(m), addr(ep) {}
msg(bdecode_node const& m, udp::endpoint const& ep): message(m), addr(ep) {}
// the message
lazy_entry const& message;
bdecode_node const& message;
// the address of the process sending or receiving
// the message.

View File

@ -99,8 +99,8 @@ struct key_desc_t
};
};
bool TORRENT_EXTRA_EXPORT verify_message(lazy_entry const* msg, key_desc_t const desc[]
, lazy_entry const* ret[], int size , char* error, int error_size);
bool TORRENT_EXTRA_EXPORT verify_message(bdecode_node const& msg, key_desc_t const desc[]
, bdecode_node ret[], int size , char* error, int error_size);
// this is the entry for every peer
// the timestamp is there to make it possible

View File

@ -33,6 +33,8 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_LAZY_ENTRY_HPP_INCLUDED
#define TORRENT_LAZY_ENTRY_HPP_INCLUDED
#ifndef TORRENT_NO_DEPRECATE
#include <utility>
#include <vector>
#include <string>
@ -41,6 +43,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/bdecode.hpp" // for error codes
namespace libtorrent
{
@ -50,9 +53,8 @@ namespace libtorrent
//
// .. _bencoded: http://wiki.theory.org/index.php/BitTorrentSpecification
//
// Whenever possible, ``lazy_bdecode()`` should be preferred over ``bdecode()``.
// It is more efficient and more secure. It supports having constraints on the
// amount of memory is consumed by the parser.
// The lazy bdecoder and lazy_entry has been deprecated in favour of
// bdecode_node and its corresponding bdecode() function.
//
// *lazy* refers to the fact that it doesn't copy any actual data out of the
// bencoded buffer. It builds a tree of ``lazy_entry`` which has pointers into
@ -79,9 +81,10 @@ namespace libtorrent
// in case the function fails. ``error_pos`` is an optional pointer to an int,
// which will be set to the byte offset into the buffer where an error occurred,
// in case the function fails.
TORRENT_DEPRECATED_PREFIX
TORRENT_EXPORT int lazy_bdecode(char const* start, char const* end
, lazy_entry& ret, error_code& ec, int* error_pos = 0
, int depth_limit = 1000, int item_limit = 1000000);
, int depth_limit = 1000, int item_limit = 1000000) TORRENT_DEPRECATED;
#ifndef TORRENT_NO_DEPRECATE
// for backwards compatibility, does not report error code
@ -392,63 +395,21 @@ namespace libtorrent
lazy_entry val;
};
// print the bencoded structure in a human-readable format to a stting
// print the bencoded structure in a human-readable format to a string
// that's returned.
TORRENT_DEPRECATED_PREFIX
TORRENT_EXPORT std::string print_entry(lazy_entry const& e
, bool single_line = false, int indent = 0);
// get the ``error_category`` for bdecode errors
TORRENT_EXPORT boost::system::error_category& get_bdecode_category();
namespace bdecode_errors
{
// libtorrent uses boost.system's ``error_code`` class to represent errors. libtorrent has
// its own error category get_bdecode_category() whith the error codes defined by error_code_enum.
enum error_code_enum
{
// Not an error
no_error = 0,
// expected string in bencoded string
expected_string,
// expected colon in bencoded string
expected_colon,
// unexpected end of file in bencoded string
unexpected_eof,
// expected value (list, dict, int or string) in bencoded string
expected_value,
// bencoded recursion depth limit exceeded
depth_exceeded,
// bencoded item count limit exceeded
limit_exceeded,
// integer overflow
overflow,
// the number of error codes
error_code_max
};
// hidden
TORRENT_EXPORT boost::system::error_code make_error_code(error_code_enum e);
}
, bool single_line = false, int indent = 0) TORRENT_DEPRECATED;
// defined in bdecode.cpp
TORRENT_DEPRECATED_PREFIX
TORRENT_EXTRA_EXPORT char const* parse_int(char const* start
, char const* end, char delimiter, boost::int64_t& val
, bdecode_errors::error_code_enum& ec);
, bdecode_errors::error_code_enum& ec) TORRENT_DEPRECATED;
}
#if BOOST_VERSION >= 103500
namespace boost { namespace system {
template<> struct is_error_code_enum<libtorrent::bdecode_errors::error_code_enum>
{ static const bool value = true; };
template<> struct is_error_condition_enum<libtorrent::bdecode_errors::error_code_enum>
{ static const bool value = true; };
} }
#endif
#endif // TORRENT_NO_DEPRECATE
#endif

View File

@ -229,7 +229,7 @@ namespace libtorrent
int next_update(time_t now) const;
void load_state(lazy_entry const& rd);
void load_state(bdecode_node const& rd);
void save_state(entry& rd) const;
// private:

View File

@ -311,14 +311,14 @@ namespace libtorrent
// to the ``entry`` that's passed in, which needs to either not be
// initialized, or initialized as a dictionary.
//
// ``load_state`` expects a lazy_entry which can be built from a bencoded
// buffer with lazy_bdecode().
// ``load_state`` expects a bdecode_node which can be built from a bencoded
// buffer with bdecode().
//
// The ``flags`` arguments passed in to ``save_state`` can be used to
// filter which parts of the session state to save. By default, all state
// is saved (except for the individual torrents). see save_state_flags_t
void save_state(entry& e, boost::uint32_t flags = 0xffffffff) const;
void load_state(lazy_entry const& e);
void load_state(bdecode_node const& e);
// .. note::
// these calls are potentially expensive and won't scale well with
@ -735,6 +735,9 @@ namespace libtorrent
void load_state(entry const& ses_state) TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
entry state() const TORRENT_DEPRECATED;
// deprecated in 1.1
TORRENT_DEPRECATED_PREFIX
void load_state(lazy_entry const& ses_state) TORRENT_DEPRECATED;
#endif // TORRENT_NO_DEPRECATE
// Sets a filter that will be used to reject and accept incoming as well

View File

@ -51,9 +51,9 @@ namespace libtorrent
namespace aux { struct session_impl; struct session_settings; }
struct settings_pack;
struct lazy_entry;
struct bdecode_node;
TORRENT_EXTRA_EXPORT settings_pack* load_pack_from_dict(lazy_entry const* settings);
TORRENT_EXTRA_EXPORT settings_pack* load_pack_from_dict(bdecode_node const& settings);
TORRENT_EXTRA_EXPORT void save_settings_to_dict(aux::session_settings const& s, entry::dictionary_type& sett);
TORRENT_EXTRA_EXPORT void apply_pack(settings_pack const* pack, aux::session_settings& sett, aux::session_impl* ses = 0);

View File

@ -37,7 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/address.hpp"
#include "libtorrent/io.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/bdecode.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/peer_id.hpp" // for sha1_hash
#include <string>
@ -123,20 +123,21 @@ namespace libtorrent
#endif
template <class EndpointType>
void read_endpoint_list(libtorrent::lazy_entry const* n, std::vector<EndpointType>& epl)
void read_endpoint_list(libtorrent::bdecode_node const& n
, std::vector<EndpointType>& epl)
{
using namespace libtorrent;
if (n->type() != lazy_entry::list_t) return;
for (int i = 0; i < n->list_size(); ++i)
if (n.type() != bdecode_node::list_t) return;
for (int i = 0; i < n.list_size(); ++i)
{
lazy_entry const* e = n->list_at(i);
if (e->type() != lazy_entry::string_t) return;
if (e->string_length() < 6) continue;
char const* in = e->string_ptr();
if (e->string_length() == 6)
bdecode_node e = n.list_at(i);
if (e.type() != bdecode_node::string_t) return;
if (e.string_length() < 6) continue;
char const* in = e.string_ptr();
if (e.string_length() == 6)
epl.push_back(read_v4_endpoint<EndpointType>(in));
#if TORRENT_USE_IPV6
else if (e->string_length() == 18)
else if (e.string_length() == 18)
epl.push_back(read_v6_endpoint<EndpointType>(in));
#endif
}

View File

@ -66,7 +66,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/file_pool.hpp" // pool_file_status
#include "libtorrent/part_file.hpp"
#include "libtorrent/stat_cache.hpp"
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/bdecode.hpp"
#include "libtorrent/bitfield.hpp"
#include "libtorrent/performance_counters.hpp"
@ -115,7 +115,7 @@ POSSIBILITY OF SUCH DAMAGE.
// virtual bool rename_file(int file, std::string const& new_name)
// { assert(false); return false; }
// virtual bool move_storage(std::string const& save_path) { return false; }
// virtual bool verify_resume_data(lazy_entry const& rd, storage_error& error) { return false; }
// virtual bool verify_resume_data(bdecode_node const& rd, storage_error& error) { return false; }
// virtual bool write_resume_data(entry& rd) const { return false; }
// virtual boost::int64_t physical_offset(int slot, int offset)
// { return slot * m_files.piece_length() + offset; };
@ -307,7 +307,7 @@ namespace libtorrent
// This function should verify the resume data ``rd`` with the files
// on disk. If the resume data seems to be up-to-date, return true. If
// not, set ``error`` to a description of what mismatched and return false.
virtual bool verify_resume_data(lazy_entry const& rd, storage_error& ec) = 0;
virtual bool verify_resume_data(bdecode_node const& rd, storage_error& ec) = 0;
// This function should fill in resume data, the current state of the
// storage, in ``rd``. The default storage adds file timestamps and
@ -423,7 +423,7 @@ namespace libtorrent
void initialize(storage_error& ec);
int move_storage(std::string const& save_path, int flags, storage_error& ec);
int sparse_end(int start) const;
bool verify_resume_data(lazy_entry const& rd, storage_error& error);
bool verify_resume_data(bdecode_node const& rd, storage_error& error);
void write_resume_data(entry& rd, storage_error& ec) const;
bool tick();
@ -519,7 +519,7 @@ namespace libtorrent
int writev(file::iovec_t const* bufs, int num_bufs, int piece
, int offset, int flags, storage_error& ec);
bool verify_resume_data(lazy_entry const&, storage_error&) { return false; }
bool verify_resume_data(bdecode_node const&, storage_error&) { return false; }
void write_resume_data(entry&, storage_error&) const {}
int m_piece_size;
@ -541,7 +541,7 @@ namespace libtorrent
, storage_error&) {}
virtual int move_storage(std::string const& /* save_path */
, int /* flags */, storage_error&) { return 0; }
virtual bool verify_resume_data(lazy_entry const& /* rd */, storage_error&)
virtual bool verify_resume_data(bdecode_node const& /* rd */, storage_error&)
{ return false; }
virtual void write_resume_data(entry&, storage_error&) const {}
virtual void release_files(storage_error&) {}
@ -674,7 +674,7 @@ namespace libtorrent
// the error message indicates that the fast resume data was rejected
// if 'fatal_disk_error' is returned, the error message indicates what
// when wrong in the disk access
int check_fastresume(lazy_entry const& rd, storage_error& error);
int check_fastresume(bdecode_node const& rd, storage_error& error);
// helper functions for check_fastresume
int check_no_fastresume(storage_error& error);

View File

@ -116,7 +116,7 @@ namespace libtorrent
struct resume_data_t
{
std::vector<char> buf;
lazy_entry entry;
bdecode_node node;
};
struct time_critical_piece
@ -1019,7 +1019,7 @@ namespace libtorrent
torrent_handle get_handle();
void write_resume_data(entry& rd) const;
void read_resume_data(lazy_entry const& rd);
void read_resume_data(bdecode_node const& rd);
void seen_complete() { m_last_seen_complete = time(0); }
int time_since_complete() const { return int(time(0) - m_last_seen_complete); }

View File

@ -49,7 +49,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/config.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/bdecode.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/time.hpp"
#include "libtorrent/assert.hpp"
@ -280,10 +280,10 @@ namespace libtorrent
// metadata will be created by libtorrent as soon as it has been
// downloaded from the swarm.
//
// The constructor that takes a lazy_entry will create a torrent_info
// The constructor that takes a bdecode_node will create a torrent_info
// object from the information found in the given torrent_file. The
// lazy_entry represents a tree node in an bencoded file. To load an
// ordinary .torrent file into a lazy_entry, use lazy_bdecode().
// bdecode_node represents a tree node in an bencoded file. To load an
// ordinary .torrent file into a bdecode_node, use bdecode().
//
// The version that takes a buffer pointer and a size will decode it as a
// .torrent file and initialize the torrent_info object for you.
@ -306,7 +306,7 @@ namespace libtorrent
//
// The ``flags`` argument is currently unused.
#ifndef BOOST_NO_EXCEPTIONS
torrent_info(lazy_entry const& torrent_file, int flags = 0);
torrent_info(bdecode_node const& torrent_file, int flags = 0);
torrent_info(char const* buffer, int size, int flags = 0);
torrent_info(std::string const& filename, int flags = 0);
#ifndef TORRENT_NO_DEPRECATE
@ -317,18 +317,24 @@ namespace libtorrent
torrent_info(std::wstring const& filename, int flags = 0) TORRENT_DEPRECATED;
#endif // TORRENT_USE_WSTRING
#endif // TORRENT_NO_DEPRECATE
#endif
#endif // BOOST_NO_EXCEPTIONS
torrent_info(torrent_info const& t);
torrent_info(sha1_hash const& info_hash, int flags = 0);
torrent_info(lazy_entry const& torrent_file, error_code& ec, int flags = 0);
torrent_info(bdecode_node const& torrent_file, error_code& ec, int flags = 0);
torrent_info(char const* buffer, int size, error_code& ec, int flags = 0);
torrent_info(std::string const& filename, error_code& ec, int flags = 0);
#ifndef TORRENT_NO_DEPRECATE
TORRENT_DEPRECATED_PREFIX
torrent_info(lazy_entry const& torrent_file, int flags = 0) TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
torrent_info(lazy_entry const& torrent_file, error_code& ec
, int flags = 0) TORRENT_DEPRECATED;
#if TORRENT_USE_WSTRING
// all wstring APIs are deprecated since 0.16.11 instead, use the wchar
// -> utf8 conversion functions and pass in utf8 strings
TORRENT_DEPRECATED_PREFIX
torrent_info(std::wstring const& filename, error_code& ec, int flags = 0) TORRENT_DEPRECATED;
torrent_info(std::wstring const& filename, error_code& ec
, int flags = 0) TORRENT_DEPRECATED;
#endif // TORRENT_USE_WSTRING
#endif // TORRENT_NO_DEPRECATE
@ -413,6 +419,11 @@ namespace libtorrent
std::vector<std::string> url_seeds() const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
std::vector<std::string> http_seeds() const TORRENT_DEPRECATED;
// deprecated in 1.1
TORRENT_DEPRECATED_PREFIX
bool parse_info_section(lazy_entry const& e, error_code& ec
, int flags) TORRENT_DEPRECATED;
#endif // TORRENT_NO_DEPRECATE
// ``web_seeds()`` returns all url seeds and http seeds in the torrent.
@ -629,23 +640,23 @@ namespace libtorrent
// populates the torrent_info by providing just the info-dict buffer.
// This is used when loading a torrent from a magnet link for instance,
// where we only have the info-dict. The lazy_entry ``e`` points to a
// where we only have the info-dict. The bdecode_node ``e`` points to a
// parsed info-dictionary. ``ec`` returns an error code if something
// fails (typically if the info dictionary is malformed). ``flags`` are
// currently unused.
bool parse_info_section(lazy_entry const& e, error_code& ec, int flags);
bool parse_info_section(bdecode_node const& e, error_code& ec, int flags);
// This function looks up keys from the info-dictionary of the loaded
// torrent file. It can be used to access extension values put in the
// .torrent file. If the specified key cannot be found, it returns NULL.
lazy_entry const* info(char const* key) const
bdecode_node info(char const* key) const
{
if (m_info_dict.type() == lazy_entry::none_t)
if (m_info_dict.type() == bdecode_node::none_t)
{
error_code ec;
lazy_bdecode(m_info_section.get(), m_info_section.get()
bdecode(m_info_section.get(), m_info_section.get()
+ m_info_section_size, m_info_dict, ec);
if (ec) return NULL;
if (ec) return bdecode_node();
}
return m_info_dict.dict_find(key);
}
@ -670,7 +681,7 @@ namespace libtorrent
// __ http://bittorrent.org/beps/bep_0030.html
bool is_merkle_torrent() const { return !m_merkle_tree.empty(); }
bool parse_torrent_file(lazy_entry const& libtorrent, error_code& ec, int flags);
bool parse_torrent_file(bdecode_node const& libtorrent, error_code& ec, int flags);
// if we're logging member offsets, we need access to them
private:
@ -726,7 +737,7 @@ namespace libtorrent
// the info section parsed. points into m_info_section
// parsed lazily
mutable lazy_entry m_info_dict;
mutable bdecode_node m_info_dict;
// if a creation date is found in the torrent file
// this will be set to that, otherwise it'll be

View File

@ -43,6 +43,7 @@ libtorrent_rasterbar_la_SOURCES = \
bandwidth_limit.cpp \
bandwidth_manager.cpp \
bandwidth_queue_entry.cpp \
bdecode.cpp \
bloom_filter.cpp \
broadcast_socket.cpp \
block_cache.cpp \

1081
src/bdecode.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1263,9 +1263,9 @@ namespace libtorrent
#ifdef TORRENT_LOGGING
peer_log("<== HASHPIECE [ piece: %d list: %d ]", p.piece, list_size);
#endif
lazy_entry hash_list;
bdecode_node hash_list;
error_code ec;
if (lazy_bdecode(recv_buffer.begin + 13, recv_buffer.begin+ 13 + list_size
if (bdecode(recv_buffer.begin + 13, recv_buffer.begin+ 13 + list_size
, hash_list, ec) != 0)
{
disconnect(errors::invalid_hash_piece, op_bittorrent, 2);
@ -1274,7 +1274,7 @@ namespace libtorrent
// the list has this format:
// [ [node-index, hash], [node-index, hash], ... ]
if (hash_list.type() != lazy_entry::list_t)
if (hash_list.type() != bdecode_node::list_t)
{
disconnect(errors::invalid_hash_list, op_bittorrent, 2);
return;
@ -1283,15 +1283,15 @@ namespace libtorrent
std::map<int, sha1_hash> nodes;
for (int i = 0; i < hash_list.list_size(); ++i)
{
lazy_entry const* e = hash_list.list_at(i);
if (e->type() != lazy_entry::list_t
|| e->list_size() != 2
|| e->list_at(0)->type() != lazy_entry::int_t
|| e->list_at(1)->type() != lazy_entry::string_t
|| e->list_at(1)->string_length() != 20) continue;
bdecode_node e = hash_list.list_at(i);
if (e.type() != bdecode_node::list_t
|| e.list_size() != 2
|| e.list_at(0).type() != bdecode_node::int_t
|| e.list_at(1).type() != bdecode_node::string_t
|| e.list_at(1).string_length() != 20) continue;
nodes.insert(std::make_pair(int(e->list_int_value_at(0))
, sha1_hash(e->list_at(1)->string_ptr())));
nodes.insert(std::make_pair(int(e.list_int_value_at(0))
, sha1_hash(e.list_at(1).string_ptr())));
}
if (!nodes.empty() && !t->add_merkle_nodes(nodes, p.piece))
{
@ -1783,11 +1783,11 @@ namespace libtorrent
buffer::const_interval recv_buffer = m_recv_buffer.get();
lazy_entry root;
bdecode_node root;
error_code ec;
int pos;
int ret = lazy_bdecode(recv_buffer.begin + 2, recv_buffer.end, root, ec, &pos);
if (ret != 0 || ec || root.type() != lazy_entry::dict_t)
int ret = bdecode(recv_buffer.begin + 2, recv_buffer.end, root, ec, &pos);
if (ret != 0 || ec || root.type() != bdecode_node::dict_t)
{
#ifdef TORRENT_LOGGING
peer_log("*** invalid extended handshake: %s pos: %d"
@ -1813,11 +1813,11 @@ namespace libtorrent
if (is_disconnecting()) return;
// upload_only
if (lazy_entry const* m = root.dict_find_dict("m"))
if (bdecode_node m = root.dict_find_dict("m"))
{
m_upload_only_id = boost::uint8_t(m->dict_find_int_value("upload_only", 0));
m_holepunch_id = boost::uint8_t(m->dict_find_int_value("ut_holepunch", 0));
m_dont_have_id = boost::uint8_t(m->dict_find_int_value("lt_donthave", 0));
m_upload_only_id = boost::uint8_t(m.dict_find_int_value("upload_only", 0));
m_holepunch_id = boost::uint8_t(m.dict_find_int_value("ut_holepunch", 0));
m_dont_have_id = boost::uint8_t(m.dict_find_int_value("lt_donthave", 0));
}
// there is supposed to be a remote listen port

View File

@ -1902,7 +1902,7 @@ namespace libtorrent
}
void disk_io_thread::async_check_fastresume(piece_manager* storage
, lazy_entry const* resume_data
, bdecode_node const* resume_data
, boost::function<void(disk_io_job const*)> const& handler)
{
#ifdef TORRENT_DEBUG
@ -2603,8 +2603,8 @@ namespace libtorrent
// if this assert fails, something's wrong with the fence logic
TORRENT_ASSERT(j->storage->num_outstanding_jobs() == 1);
lazy_entry const* rd = (lazy_entry const*)j->buffer;
lazy_entry tmp;
bdecode_node const* rd = (bdecode_node const*)j->buffer;
bdecode_node tmp;
if (rd == NULL) rd = &tmp;
return j->storage->check_fastresume(*rd, j->error);

View File

@ -38,7 +38,10 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/entry.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/escape_string.hpp"
#ifndef TORRENT_NO_DEPRECATE
#include "libtorrent/lazy_entry.hpp"
#endif
#include "libtorrent/bdecode.hpp"
#include "libtorrent/escape_string.hpp"
#if defined(_MSC_VER)
@ -314,6 +317,44 @@ namespace libtorrent
m_type = int_t;
}
// convert a bdecode_node into an old skool entry
void entry::operator=(bdecode_node const& e)
{
switch (e.type())
{
case bdecode_node::string_t:
this->string() = e.string_value();
break;
case bdecode_node::int_t:
this->integer() = e.int_value();
break;
case bdecode_node::dict_t:
{
dictionary_type& d = this->dict();
for (int i = 0; i < e.dict_size(); ++i)
{
std::pair<std::string, bdecode_node> elem = e.dict_at(i);
d[elem.first] = elem.second;
}
break;
}
case bdecode_node::list_t:
{
list_type& l = this->list();
for (int i = 0; i < e.list_size(); ++i)
{
l.push_back(entry());
l.back() = e.list_at(i);
}
break;
}
case bdecode_node::none_t:
destruct();
break;
}
}
#ifndef TORRENT_NO_DEPRECATE
// convert a lazy_entry into an old skool entry
void entry::operator=(lazy_entry const& e)
{
@ -350,6 +391,7 @@ namespace libtorrent
break;
}
}
#endif
void entry::operator=(dictionary_type const& v)
{

View File

@ -377,18 +377,18 @@ namespace libtorrent
close();
}
bool extract_peer_info(lazy_entry const& info, peer_entry& ret, error_code& ec)
bool extract_peer_info(bdecode_node const& info, peer_entry& ret, error_code& ec)
{
// extract peer id (if any)
if (info.type() != lazy_entry::dict_t)
if (info.type() != bdecode_node::dict_t)
{
ec.assign(errors::invalid_peer_dict, get_libtorrent_category());
return false;
}
lazy_entry const* i = info.dict_find_string("peer id");
if (i != 0 && i->string_length() == 20)
bdecode_node i = info.dict_find_string("peer id");
if (i && i.string_length() == 20)
{
std::copy(i->string_ptr(), i->string_ptr()+20, ret.pid.begin());
std::copy(i.string_ptr(), i.string_ptr()+20, ret.pid.begin());
}
else
{
@ -403,7 +403,7 @@ namespace libtorrent
ec.assign(errors::invalid_tracker_response, get_libtorrent_category());
return false;
}
ret.hostname = i->string_value();
ret.hostname = i.string_value();
// extract port
i = info.dict_find_int("port");
@ -412,7 +412,7 @@ namespace libtorrent
ec.assign(errors::invalid_tracker_response, get_libtorrent_category());
return false;
}
ret.port = (unsigned short)i->int_value();
ret.port = (unsigned short)i.int_value();
return true;
}
@ -422,12 +422,12 @@ namespace libtorrent
{
tracker_response resp;
lazy_entry e;
int res = lazy_bdecode(data, data + size, e, ec);
bdecode_node e;
int res = bdecode(data, data + size, e, ec);
if (ec) return resp;
if (res != 0 || e.type() != lazy_entry::dict_t)
if (res != 0 || e.type() != bdecode_node::dict_t)
{
ec.assign(errors::invalid_tracker_response, get_libtorrent_category());
return resp;
@ -441,45 +441,45 @@ namespace libtorrent
resp.interval = interval;
resp.min_interval = min_interval;
lazy_entry const* tracker_id = e.dict_find_string("tracker id");
bdecode_node tracker_id = e.dict_find_string("tracker id");
if (tracker_id)
resp.trackerid = tracker_id->string_value();
resp.trackerid = tracker_id.string_value();
// parse the response
lazy_entry const* failure = e.dict_find_string("failure reason");
bdecode_node failure = e.dict_find_string("failure reason");
if (failure)
{
resp.failure_reason = failure->string_value();
resp.failure_reason = failure.string_value();
ec.assign(errors::tracker_failure, get_libtorrent_category());
return resp;
}
lazy_entry const* warning = e.dict_find_string("warning message");
bdecode_node warning = e.dict_find_string("warning message");
if (warning)
resp.warning_message = warning->string_value();
resp.warning_message = warning.string_value();
if (scrape_request)
{
lazy_entry const* files = e.dict_find_dict("files");
if (files == 0)
bdecode_node files = e.dict_find_dict("files");
if (!files)
{
ec.assign(errors::invalid_files_entry, get_libtorrent_category());
return resp;
}
lazy_entry const* scrape_data = files->dict_find_dict(
bdecode_node scrape_data = files.dict_find_dict(
scrape_ih.to_string());
if (scrape_data == 0)
if (!scrape_data)
{
ec.assign(errors::invalid_hash_entry, get_libtorrent_category());
return resp;
}
resp.complete = int(scrape_data->dict_find_int_value("complete", -1));
resp.incomplete = int(scrape_data->dict_find_int_value("incomplete", -1));
resp.downloaded = int(scrape_data->dict_find_int_value("downloaded", -1));
resp.downloaders = int(scrape_data->dict_find_int_value("downloaders", -1));
resp.complete = int(scrape_data.dict_find_int_value("complete", -1));
resp.incomplete = int(scrape_data.dict_find_int_value("incomplete", -1));
resp.downloaded = int(scrape_data.dict_find_int_value("downloaded", -1));
resp.downloaders = int(scrape_data.dict_find_int_value("downloaders", -1));
return resp;
}
@ -489,11 +489,11 @@ namespace libtorrent
resp.incomplete = int(e.dict_find_int_value("incomplete", -1));
resp.downloaded = int(e.dict_find_int_value("downloaded", -1));
lazy_entry const* peers_ent = e.dict_find("peers");
if (peers_ent && peers_ent->type() == lazy_entry::string_t)
bdecode_node peers_ent = e.dict_find("peers");
if (peers_ent && peers_ent.type() == bdecode_node::string_t)
{
char const* peers = peers_ent->string_ptr();
int len = peers_ent->string_length();
char const* peers = peers_ent.string_ptr();
int len = peers_ent.string_length();
resp.peers4.reserve(len / 6);
for (int i = 0; i < len; i += 6)
{
@ -506,15 +506,15 @@ namespace libtorrent
resp.peers4.push_back(p);
}
}
else if (peers_ent && peers_ent->type() == lazy_entry::list_t)
else if (peers_ent && peers_ent.type() == bdecode_node::list_t)
{
int len = peers_ent->list_size();
int len = peers_ent.list_size();
resp.peers.reserve(len);
error_code parse_error;
for (int i = 0; i < len; ++i)
{
peer_entry p;
if (!extract_peer_info(*peers_ent->list_at(i), p, parse_error))
if (!extract_peer_info(peers_ent.list_at(i), p, parse_error))
continue;
resp.peers.push_back(p);
}
@ -528,15 +528,15 @@ namespace libtorrent
}
else
{
peers_ent = 0;
peers_ent.clear();
}
#if TORRENT_USE_IPV6
lazy_entry const* ipv6_peers = e.dict_find_string("peers6");
bdecode_node ipv6_peers = e.dict_find_string("peers6");
if (ipv6_peers)
{
char const* peers = ipv6_peers->string_ptr();
int len = ipv6_peers->string_length();
char const* peers = ipv6_peers.string_ptr();
int len = ipv6_peers.string_length();
resp.peers6.reserve(len / 18);
for (int i = 0; i < len; i += 18)
{
@ -550,10 +550,10 @@ namespace libtorrent
}
else
{
ipv6_peers = 0;
ipv6_peers.clear();
}
#else
lazy_entry const* ipv6_peers = 0;
bdecode_node ipv6_peers = 0;
#endif
/*
// if we didn't receive any peers. We don't care if we're stopping anyway
@ -564,14 +564,14 @@ namespace libtorrent
return resp;
}
*/
lazy_entry const* ip_ent = e.dict_find_string("external ip");
bdecode_node ip_ent = e.dict_find_string("external ip");
if (ip_ent)
{
char const* p = ip_ent->string_ptr();
if (ip_ent->string_length() == int(address_v4::bytes_type().size()))
char const* p = ip_ent.string_ptr();
if (ip_ent.string_length() == int(address_v4::bytes_type().size()))
resp.external_ip = detail::read_v4_address(p);
#if TORRENT_USE_IPV6
else if (ip_ent->string_length() == int(address_v6::bytes_type().size()))
else if (ip_ent.string_length() == int(address_v6::bytes_type().size()))
resp.external_ip = detail::read_v6_address(p);
#endif
}

View File

@ -72,9 +72,9 @@ namespace libtorrent { namespace dht
void incoming_error(entry& e, char const* msg);
#ifdef TORRENT_DHT_VERBOSE_LOGGING
std::string parse_dht_client(lazy_entry const& e)
std::string parse_dht_client(bdecode_node const& e)
{
lazy_entry const* ver = e.dict_find_string("v");
bdecode_node ver = e.dict_find_string("v");
if (!ver) return "generic";
std::string const& client = ver->string_value();
if (client.size() < 2)
@ -116,12 +116,12 @@ namespace libtorrent { namespace dht
TORRENT_DEFINE_LOG(dht_tracker)
#endif
node_id extract_node_id(lazy_entry const* e)
node_id extract_node_id(bdecode_node e)
{
if (e == 0 || e->type() != lazy_entry::dict_t) return (node_id::min)();
lazy_entry const* nid = e->dict_find_string("node-id");
if (nid == 0 || nid->string_length() != 20) return (node_id::min)();
return node_id(node_id(nid->string_ptr()));
if (!e || e.type() != bdecode_node::dict_t) return (node_id::min)();
bdecode_node nid = e.dict_find_string("node-id");
if (!nid || nid.string_length() != 20) return (node_id::min)();
return node_id(node_id(nid.string_ptr()));
}
node_id extract_node_id(entry const* e)
@ -135,7 +135,8 @@ namespace libtorrent { namespace dht
// class that puts the networking and the kademlia node in a single
// unit and connecting them together.
dht_tracker::dht_tracker(libtorrent::aux::session_impl& ses, rate_limited_udp_socket& sock
dht_tracker::dht_tracker(libtorrent::aux::session_impl& ses
, rate_limited_udp_socket& sock
, dht_settings const& settings, counters& cnt, entry const* state)
: m_counters(cnt)
, m_dht(&ses, this, settings, extract_node_id(state)
@ -391,10 +392,9 @@ namespace libtorrent { namespace dht
TORRENT_ASSERT(size > 0);
lazy_entry e;
int pos;
error_code err;
int ret = lazy_bdecode(buf, buf + size, e, err, &pos, 10, 500);
int ret = bdecode(buf, buf + size, m_msg, err, &pos, 10, 500);
if (ret != 0)
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
@ -404,9 +404,7 @@ namespace libtorrent { namespace dht
return false;
}
libtorrent::dht::msg m(e, ep);
if (e.type() != lazy_entry::dict_t)
if (m_msg.type() != bdecode_node::dict_t)
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(dht_tracker) << "<== " << ep << " ERROR: not a dictionary: "
@ -420,6 +418,7 @@ namespace libtorrent { namespace dht
return false;
}
libtorrent::dht::msg m(m_msg, ep);
m_dht.incoming(m);
return true;
}
@ -503,8 +502,8 @@ namespace libtorrent { namespace dht
#ifdef TORRENT_DHT_VERBOSE_LOGGING
std::stringstream log_line;
lazy_entry print;
int ret = lazy_bdecode(&m_send_buf[0], &m_send_buf[0] + m_send_buf.size(), print, ec);
bdecode_node print;
int ret = bdecode(&m_send_buf[0], &m_send_buf[0] + m_send_buf.size(), print, ec);
TORRENT_ASSERT(ret == 0);
log_line << print_entry(print, true);
#endif

View File

@ -54,7 +54,7 @@ using detail::read_v6_endpoint;
void find_data_observer::reply(msg const& m)
{
lazy_entry const* r = m.message.dict_find_dict("r");
bdecode_node r = m.message.dict_find_dict("r");
if (!r)
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
@ -63,19 +63,19 @@ void find_data_observer::reply(msg const& m)
return;
}
lazy_entry const* id = r->dict_find_string("id");
if (!id || id->string_length() != 20)
bdecode_node id = r.dict_find_string("id");
if (!id || id.string_length() != 20)
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(traversal) << "[" << m_algorithm.get() << "] invalid id in response";
#endif
return;
}
lazy_entry const* token = r->dict_find_string("token");
bdecode_node token = r.dict_find_string("token");
if (token)
{
static_cast<find_data*>(m_algorithm.get())->got_write_token(
node_id(id->string_ptr()), token->string_value());
node_id(id.string_ptr()), token.string_value());
}
traversal_observer::reply(m);

View File

@ -42,7 +42,7 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent { namespace dht
{
void get_item::got_data(lazy_entry const* v,
void get_item::got_data(bdecode_node const& v,
char const* pk,
boost::uint64_t seq,
char const* sig)
@ -55,7 +55,7 @@ void get_item::got_data(lazy_entry const* v,
if (pk)
incoming_target = item_target_id(salt, pk);
else
incoming_target = item_target_id(v->data_section());
incoming_target = item_target_id(v.data_section());
if (incoming_target != m_target) return;
@ -248,7 +248,7 @@ void get_item_observer::reply(msg const& m)
char const* sig = NULL;
boost::uint64_t seq = 0;
lazy_entry const* r = m.message.dict_find_dict("r");
bdecode_node r = m.message.dict_find_dict("r");
if (!r)
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
@ -257,21 +257,21 @@ void get_item_observer::reply(msg const& m)
return;
}
lazy_entry const* k = r->dict_find_string("k");
if (k && k->string_length() == item_pk_len)
pk = k->string_ptr();
bdecode_node k = r.dict_find_string("k");
if (k && k.string_length() == item_pk_len)
pk = k.string_ptr();
lazy_entry const* s = r->dict_find_string("sig");
if (s && s->string_length() == item_sig_len)
sig = s->string_ptr();
bdecode_node s = r.dict_find_string("sig");
if (s && s.string_length() == item_sig_len)
sig = s.string_ptr();
lazy_entry const* q = r->dict_find_int("seq");
bdecode_node q = r.dict_find_int("seq");
if (q)
seq = q->int_value();
seq = q.int_value();
else if (pk && sig)
return;
lazy_entry const* v = r->dict_find("v");
bdecode_node v = r.dict_find("v");
if (v)
{
static_cast<get_item*>(m_algorithm.get())->got_data(v, pk, seq, sig);

View File

@ -47,7 +47,7 @@ using detail::read_v6_endpoint;
void get_peers_observer::reply(msg const& m)
{
lazy_entry const* r = m.message.dict_find_dict("r");
bdecode_node r = m.message.dict_find_dict("r");
if (!r)
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
@ -57,27 +57,27 @@ void get_peers_observer::reply(msg const& m)
}
// look for peers
lazy_entry const* n = r->dict_find_list("values");
bdecode_node n = r.dict_find_list("values");
if (n)
{
std::vector<tcp::endpoint> peer_list;
if (n->list_size() == 1 && n->list_at(0)->type() == lazy_entry::string_t)
if (n.list_size() == 1 && n.list_at(0).type() == bdecode_node::string_t)
{
// assume it's mainline format
char const* peers = n->list_at(0)->string_ptr();
char const* end = peers + n->list_at(0)->string_length();
char const* peers = n.list_at(0).string_ptr();
char const* end = peers + n.list_at(0).string_length();
#ifdef TORRENT_DHT_VERBOSE_LOGGING
lazy_entry const* id = r->dict_find_string("id");
if (id && id->string_length() == 20)
bdecode_node id = r.dict_find_string("id");
if (id && id.string_length() == 20)
{
TORRENT_LOG(traversal)
<< "[" << m_algorithm.get() << "] PEERS"
<< " invoke-count: " << m_algorithm->invoke_count()
<< " branch-factor: " << m_algorithm->branch_factor()
<< " invoke-count: " << m_algorithm.invoke_count()
<< " branch-factor: " << m_algorithm.branch_factor()
<< " addr: " << m.addr
<< " id: " << node_id(id->string_ptr())
<< " distance: " << distance_exp(m_algorithm->target(), node_id(id->string_ptr()))
<< " id: " << node_id(id.string_ptr())
<< " distance: " << distance_exp(m_algorithm.target(), node_id(id.string_ptr()))
<< " p: " << ((end - peers) / 6);
}
#endif
@ -89,17 +89,17 @@ void get_peers_observer::reply(msg const& m)
// assume it's uTorrent/libtorrent format
read_endpoint_list<tcp::endpoint>(n, peer_list);
#ifdef TORRENT_DHT_VERBOSE_LOGGING
lazy_entry const* id = r->dict_find_string("id");
if (id && id->string_length() == 20)
bdecode_node id = r.dict_find_string("id");
if (id && id.string_length() == 20)
{
TORRENT_LOG(traversal)
<< "[" << m_algorithm.get() << "] PEERS"
<< " invoke-count: " << m_algorithm->invoke_count()
<< " branch-factor: " << m_algorithm->branch_factor()
<< " addr: " << m.addr
<< " id: " << node_id(id->string_ptr())
<< " id: " << node_id(id.string_ptr())
<< " distance: " << distance_exp(m_algorithm->target(), node_id(id->string_ptr()))
<< " p: " << n->list_size();
<< " p: " << n.list_size();
}
#endif
}
@ -295,7 +295,7 @@ void obfuscated_get_peers::done()
void obfuscated_get_peers_observer::reply(msg const& m)
{
lazy_entry const* r = m.message.dict_find_dict("r");
bdecode_node r = m.message.dict_find_dict("r");
if (!r)
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
@ -305,8 +305,8 @@ void obfuscated_get_peers_observer::reply(msg const& m)
return;
}
lazy_entry const* id = r->dict_find_string("id");
if (!id || id->string_length() != 20)
bdecode_node id = r.dict_find_string("id");
if (!id || id.string_length() != 20)
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(traversal) << "[" << m_algorithm.get()

View File

@ -36,7 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <libtorrent/ed25519.hpp>
#ifdef TORRENT_DEBUG
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/bdecode.hpp"
#endif
#ifdef TORRENT_USE_VALGRIND
@ -54,9 +54,9 @@ namespace
{
// v must be valid bencoding!
#ifdef TORRENT_DEBUG
lazy_entry e;
bdecode_node e;
error_code ec;
TORRENT_ASSERT(lazy_bdecode(v.first, v.first + v.second, e, ec) == 0);
TORRENT_ASSERT(bdecode(v.first, v.first + v.second, e, ec) == 0);
#endif
char* ptr = out;
@ -185,14 +185,14 @@ void item::assign(entry const& v, std::pair<char const*, int> salt
m_mutable = false;
}
bool item::assign(lazy_entry const* v
bool item::assign(bdecode_node const& v
, std::pair<char const*, int> salt
, boost::uint64_t seq, char const* pk, char const* sig)
{
TORRENT_ASSERT(v->data_section().second <= 1000);
TORRENT_ASSERT(v.data_section().second <= 1000);
if (pk && sig)
{
if (!verify_mutable_item(v->data_section(), salt, seq, pk, sig))
if (!verify_mutable_item(v.data_section(), salt, seq, pk, sig))
return false;
memcpy(m_pk.c_array(), pk, item_pk_len);
memcpy(m_sig.c_array(), sig, item_sig_len);
@ -206,7 +206,7 @@ bool item::assign(lazy_entry const* v
else
m_mutable = false;
m_value = *v;
m_value = v;
return true;
}

View File

@ -221,44 +221,44 @@ void node_impl::unreachable(udp::endpoint const& ep)
void node_impl::incoming(msg const& m)
{
// is this a reply?
lazy_entry const* y_ent = m.message.dict_find_string("y");
if (!y_ent || y_ent->string_length() == 0)
bdecode_node y_ent = m.message.dict_find_string("y");
if (!y_ent || y_ent.string_length() == 0)
{
// don't respond to this obviously broken messages. We don't
// want to open up a magnification opportunity
// entry e;
// incoming_error(e, "missing 'y' entry");
// m_sock->send_packet(e, m.addr, 0);
// m_sock.send_packet(e, m.addr, 0);
return;
}
char y = *(y_ent->string_ptr());
char y = *(y_ent.string_ptr());
lazy_entry const* ext_ip = m.message.dict_find_string("ip");
bdecode_node ext_ip = m.message.dict_find_string("ip");
// backwards compatibility
if (ext_ip == NULL)
if (!ext_ip)
{
lazy_entry const* r = m.message.dict_find_dict("r");
bdecode_node r = m.message.dict_find_dict("r");
if (r)
ext_ip = r->dict_find_string("ip");
ext_ip = r.dict_find_string("ip");
}
#if TORRENT_USE_IPV6
if (ext_ip && ext_ip->string_length() >= 16)
if (ext_ip && ext_ip.string_length() >= 16)
{
// this node claims we use the wrong node-ID!
address_v6::bytes_type b;
memcpy(&b[0], ext_ip->string_ptr(), 16);
memcpy(&b[0], ext_ip.string_ptr(), 16);
if (m_observer)
m_observer->set_external_address(address_v6(b)
, m.addr.address());
} else
#endif
if (ext_ip && ext_ip->string_length() >= 4)
if (ext_ip && ext_ip.string_length() >= 4)
{
address_v4::bytes_type b;
memcpy(&b[0], ext_ip->string_ptr(), 4);
memcpy(&b[0], ext_ip.string_ptr(), 4);
if (m_observer)
m_observer->set_external_address(address_v4(b)
, m.addr.address());
@ -283,10 +283,10 @@ void node_impl::incoming(msg const& m)
case 'e':
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
lazy_entry const* err = m.message.dict_find_list("e");
if (err && err->list_size() >= 2)
bdecode_node err = m.message.dict_find_list("e");
if (err && err.list_size() >= 2)
{
TORRENT_LOG(node) << "INCOMING ERROR: " << err->list_string_value_at(1);
TORRENT_LOG(node) << "INCOMING ERROR: " << err.list_string_value_at(1);
}
#endif
node_id id;
@ -419,7 +419,7 @@ struct ping_observer : observer
{
flags |= flag_done;
lazy_entry const* r = m.message.dict_find_dict("r");
bdecode_node r = m.message.dict_find_dict("r");
if (!r)
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
@ -430,11 +430,11 @@ struct ping_observer : observer
}
// look for nodes
lazy_entry const* n = r->dict_find_string("nodes");
bdecode_node n = r.dict_find_string("nodes");
if (n)
{
char const* nodes = n->string_ptr();
char const* end = nodes + n->string_length();
char const* nodes = n.string_ptr();
char const* end = nodes + n.string_length();
while (end - nodes >= 26)
{
@ -674,18 +674,23 @@ using detail::write_nodes_entry;
// verifies that a message has all the required
// entries and returns them in ret
bool verify_message(lazy_entry const* msg, key_desc_t const desc[], lazy_entry const* ret[]
, int size , char* error, int error_size)
bool verify_message(bdecode_node const& message, key_desc_t const desc[]
, bdecode_node ret[], int size , char* error, int error_size)
{
// get a non-root bdecode_node that still
// points to the root. message should not be copied
bdecode_node msg = message.non_owning();
// clear the return buffer
memset(ret, 0, sizeof(ret[0]) * size);
for (int i = 0; i < size; ++i)
ret[i].clear();
// when parsing child nodes, this is the stack
// of lazy_entry pointers to return to
lazy_entry const* stack[5];
// of bdecode_nodes to return to
bdecode_node stack[5];
int stack_ptr = -1;
if (msg->type() != lazy_entry::dict_t)
if (msg.type() != bdecode_node::dict_t)
{
snprintf(error, error_size, "not a dictionary");
return false;
@ -698,9 +703,10 @@ bool verify_message(lazy_entry const* msg, key_desc_t const desc[], lazy_entry c
// fprintf(stderr, "looking for %s in %s\n", k.name, print_entry(*msg).c_str());
ret[i] = msg->dict_find(k.name);
ret[i] = msg.dict_find(k.name);
// none_t means any type
if (ret[i] && ret[i]->type() != k.type && k.type != lazy_entry::none_t) ret[i] = 0;
if (ret[i] && ret[i].type() != k.type && k.type != bdecode_node::none_t)
ret[i].clear();
if (ret[i] == 0 && (k.flags & key_desc_t::optional) == 0)
{
// the key was not found, and it's not an optional key
@ -710,18 +716,18 @@ bool verify_message(lazy_entry const* msg, key_desc_t const desc[], lazy_entry c
if (k.size > 0
&& ret[i]
&& k.type == lazy_entry::string_t)
&& k.type == bdecode_node::string_t)
{
bool invalid = false;
if (k.flags & key_desc_t::size_divisible)
invalid = (ret[i]->string_length() % k.size) != 0;
invalid = (ret[i].string_length() % k.size) != 0;
else
invalid = ret[i]->string_length() != k.size;
invalid = ret[i].string_length() != k.size;
if (invalid)
{
// the string was not of the required size
ret[i] = 0;
ret[i].clear();
if ((k.flags & key_desc_t::optional) == 0)
{
snprintf(error, error_size, "invalid value for '%s'", k.name);
@ -731,7 +737,7 @@ bool verify_message(lazy_entry const* msg, key_desc_t const desc[], lazy_entry c
}
if (k.flags & key_desc_t::parse_children)
{
TORRENT_ASSERT(k.type == lazy_entry::dict_t);
TORRENT_ASSERT(k.type == bdecode_node::dict_t);
if (ret[i])
{
@ -805,15 +811,16 @@ void node_impl::incoming_request(msg const& m, entry& e)
e["t"] = m.message.dict_find_string_value("t");
key_desc_t top_desc[] = {
{"q", lazy_entry::string_t, 0, 0},
{"ro", lazy_entry::int_t, 0, key_desc_t::optional},
{"a", lazy_entry::dict_t, 0, key_desc_t::parse_children},
{"id", lazy_entry::string_t, 20, key_desc_t::last_child},
{"q", bdecode_node::string_t, 0, 0},
{"ro", bdecode_node::int_t, 0, key_desc_t::optional},
{"a", bdecode_node::dict_t, 0, key_desc_t::parse_children},
{"id", bdecode_node::string_t, 20, key_desc_t::last_child},
};
lazy_entry const* top_level[4];
bdecode_node top_level[4];
char error_string[200];
if (!verify_message(&m.message, top_desc, top_level, 4, error_string, sizeof(error_string)))
if (!verify_message(m.message, top_desc, top_level, 4, error_string
, sizeof(error_string)))
{
incoming_error(e, error_string);
return;
@ -821,11 +828,12 @@ void node_impl::incoming_request(msg const& m, entry& e)
e["ip"] = endpoint_to_bytes(m.addr);
char const* query = top_level[0]->string_cstr();
char const* query = top_level[0].string_ptr();
int query_len = top_level[0].string_length();
lazy_entry const* arg_ent = top_level[2];
bool read_only = top_level[1] && top_level[1]->int_value() != 0;
node_id id(top_level[3]->string_ptr());
bdecode_node arg_ent = top_level[2];
bool read_only = top_level[1] && top_level[1].int_value() != 0;
node_id id(top_level[3].string_ptr());
// if this nodes ID doesn't match its IP, tell it what
// its IP is with an error
@ -845,21 +853,21 @@ void node_impl::incoming_request(msg const& m, entry& e)
// mirror back the other node's external port
reply["p"] = m.addr.port();
if (strcmp(query, "ping") == 0)
if (query_len == 4 && memcmp(query, "ping", 4) == 0)
{
m_counters.inc_stats_counter(counters::dht_ping_in);
// we already have 't' and 'id' in the response
// no more left to add
}
else if (strcmp(query, "get_peers") == 0)
else if (query_len == 9 && memcmp(query, "get_peers", 9) == 0)
{
key_desc_t msg_desc[] = {
{"info_hash", lazy_entry::string_t, 20, 0},
{"noseed", lazy_entry::int_t, 0, key_desc_t::optional},
{"scrape", lazy_entry::int_t, 0, key_desc_t::optional},
{"info_hash", bdecode_node::string_t, 20, 0},
{"noseed", bdecode_node::int_t, 0, key_desc_t::optional},
{"scrape", bdecode_node::int_t, 0, key_desc_t::optional},
};
lazy_entry const* msg_keys[3];
bdecode_node msg_keys[3];
if (!verify_message(arg_ent, msg_desc, msg_keys, 3, error_string
, sizeof(error_string)))
{
@ -868,11 +876,11 @@ void node_impl::incoming_request(msg const& m, entry& e)
return;
}
reply["token"] = generate_token(m.addr, msg_keys[0]->string_ptr());
reply["token"] = generate_token(m.addr, msg_keys[0].string_ptr());
m_counters.inc_stats_counter(counters::dht_get_peers_in);
sha1_hash info_hash(msg_keys[0]->string_ptr());
sha1_hash info_hash(msg_keys[0].string_ptr());
nodes_t n;
// always return nodes as well as peers
m_table.find_node(info_hash, n, 0);
@ -880,8 +888,8 @@ void node_impl::incoming_request(msg const& m, entry& e)
bool noseed = false;
bool scrape = false;
if (msg_keys[1] && msg_keys[1]->int_value() != 0) noseed = true;
if (msg_keys[2] && msg_keys[2]->int_value() != 0) scrape = true;
if (msg_keys[1] && msg_keys[1].int_value() != 0) noseed = true;
if (msg_keys[2] && msg_keys[2].int_value() != 0) scrape = true;
lookup_peers(info_hash, reply, noseed, scrape);
#ifdef TORRENT_DHT_VERBOSE_LOGGING
if (reply.find_key("values"))
@ -890,13 +898,13 @@ void node_impl::incoming_request(msg const& m, entry& e)
}
#endif
}
else if (strcmp(query, "find_node") == 0)
else if (query_len == 9 && memcmp(query, "find_node", 9) == 0)
{
key_desc_t msg_desc[] = {
{"target", lazy_entry::string_t, 20, 0},
{"target", bdecode_node::string_t, 20, 0},
};
lazy_entry const* msg_keys[1];
bdecode_node msg_keys[1];
if (!verify_message(arg_ent, msg_desc, msg_keys, 1, error_string, sizeof(error_string)))
{
incoming_error(e, error_string);
@ -904,25 +912,25 @@ void node_impl::incoming_request(msg const& m, entry& e)
}
m_counters.inc_stats_counter(counters::dht_find_node_in);
sha1_hash target(msg_keys[0]->string_ptr());
sha1_hash target(msg_keys[0].string_ptr());
// TODO: 2 find_node should write directly to the response entry
nodes_t n;
m_table.find_node(target, n, 0);
write_nodes_entry(reply, n);
}
else if (strcmp(query, "announce_peer") == 0)
else if (query_len == 13 && memcmp(query, "announce_peer", 13) == 0)
{
key_desc_t msg_desc[] = {
{"info_hash", lazy_entry::string_t, 20, 0},
{"port", lazy_entry::int_t, 0, 0},
{"token", lazy_entry::string_t, 0, 0},
{"n", lazy_entry::string_t, 0, key_desc_t::optional},
{"seed", lazy_entry::int_t, 0, key_desc_t::optional},
{"implied_port", lazy_entry::int_t, 0, key_desc_t::optional},
{"info_hash", bdecode_node::string_t, 20, 0},
{"port", bdecode_node::int_t, 0, 0},
{"token", bdecode_node::string_t, 0, 0},
{"n", bdecode_node::string_t, 0, key_desc_t::optional},
{"seed", bdecode_node::int_t, 0, key_desc_t::optional},
{"implied_port", bdecode_node::int_t, 0, key_desc_t::optional},
};
lazy_entry const* msg_keys[6];
bdecode_node msg_keys[6];
if (!verify_message(arg_ent, msg_desc, msg_keys, 6, error_string, sizeof(error_string)))
{
m_counters.inc_stats_counter(counters::dht_invalid_announce);
@ -930,11 +938,11 @@ void node_impl::incoming_request(msg const& m, entry& e)
return;
}
int port = int(msg_keys[1]->int_value());
int port = int(msg_keys[1].int_value());
// is the announcer asking to ignore the explicit
// listen port and instead use the source port of the packet?
if (msg_keys[5] && msg_keys[5]->int_value() != 0)
if (msg_keys[5] && msg_keys[5].int_value() != 0)
port = m.addr.port();
if (port < 0 || port >= 65536)
@ -944,7 +952,7 @@ void node_impl::incoming_request(msg const& m, entry& e)
return;
}
sha1_hash info_hash(msg_keys[0]->string_ptr());
sha1_hash info_hash(msg_keys[0].string_ptr());
if (m_post_alert)
{
@ -952,7 +960,7 @@ void node_impl::incoming_request(msg const& m, entry& e)
if (!m_post_alert->post_alert(a)) delete a;
}
if (!verify_token(msg_keys[2]->string_value(), msg_keys[0]->string_ptr(), m.addr))
if (!verify_token(msg_keys[2].string_value(), msg_keys[0].string_ptr(), m.addr))
{
m_counters.inc_stats_counter(counters::dht_invalid_announce);
incoming_error(e, "invalid token");
@ -1001,7 +1009,7 @@ void node_impl::incoming_request(msg const& m, entry& e)
// for this torrent. Store it.
if (msg_keys[3] && v->name.empty())
{
std::string name = msg_keys[3]->string_value();
std::string name = msg_keys[3].string_value();
if (name.size() > 50) name.resize(50);
v->name = name;
}
@ -1009,28 +1017,28 @@ void node_impl::incoming_request(msg const& m, entry& e)
peer_entry peer;
peer.addr = tcp::endpoint(m.addr.address(), port);
peer.added = aux::time_now();
peer.seed = msg_keys[4] && msg_keys[4]->int_value();
peer.seed = msg_keys[4] && msg_keys[4].int_value();
std::set<peer_entry>::iterator i = v->peers.find(peer);
if (i != v->peers.end()) v->peers.erase(i++);
v->peers.insert(i, peer);
}
else if (strcmp(query, "put") == 0)
else if (query_len == 3 && memcmp(query, "put", 3) == 0)
{
// the first 2 entries are for both mutable and
// immutable puts
const static key_desc_t msg_desc[] = {
{"token", lazy_entry::string_t, 0, 0},
{"v", lazy_entry::none_t, 0, 0},
{"seq", lazy_entry::int_t, 0, key_desc_t::optional},
{"token", bdecode_node::string_t, 0, 0},
{"v", bdecode_node::none_t, 0, 0},
{"seq", bdecode_node::int_t, 0, key_desc_t::optional},
// public key
{"k", lazy_entry::string_t, item_pk_len, key_desc_t::optional},
{"sig", lazy_entry::string_t, item_sig_len, key_desc_t::optional},
{"cas", lazy_entry::int_t, 0, key_desc_t::optional},
{"salt", lazy_entry::string_t, 0, key_desc_t::optional},
{"k", bdecode_node::string_t, item_pk_len, key_desc_t::optional},
{"sig", bdecode_node::string_t, item_sig_len, key_desc_t::optional},
{"cas", bdecode_node::int_t, 0, key_desc_t::optional},
{"salt", bdecode_node::string_t, 0, key_desc_t::optional},
};
// attempt to parse the message
lazy_entry const* msg_keys[7];
bdecode_node msg_keys[7];
if (!verify_message(arg_ent, msg_desc, msg_keys, 7, error_string, sizeof(error_string)))
{
m_counters.inc_stats_counter(counters::dht_invalid_put);
@ -1045,14 +1053,14 @@ void node_impl::incoming_request(msg const& m, entry& e)
// public key (only set if it's a mutable put)
char const* pk = NULL;
if (msg_keys[3]) pk = msg_keys[3]->string_ptr();
if (msg_keys[3]) pk = msg_keys[3].string_ptr();
// signature (only set if it's a mutable put)
char const* sig = NULL;
if (msg_keys[4]) sig = msg_keys[4]->string_ptr();
if (msg_keys[4]) sig = msg_keys[4].string_ptr();
// pointer and length to the whole entry
std::pair<char const*, int> buf = msg_keys[1]->data_section();
std::pair<char const*, int> buf = msg_keys[1].data_section();
if (buf.second > 1000 || buf.second <= 0)
{
m_counters.inc_stats_counter(counters::dht_invalid_put);
@ -1063,7 +1071,7 @@ void node_impl::incoming_request(msg const& m, entry& e)
std::pair<char const*, int> salt(static_cast<char const*>(NULL), 0);
if (msg_keys[6])
salt = std::pair<char const*, int>(
msg_keys[6]->string_ptr(), msg_keys[6]->string_length());
msg_keys[6].string_ptr(), msg_keys[6].string_length());
if (salt.second > 64)
{
m_counters.inc_stats_counter(counters::dht_invalid_put);
@ -1085,7 +1093,7 @@ void node_impl::incoming_request(msg const& m, entry& e)
// verify the write-token. tokens are only valid to write to
// specific target hashes. it must match the one we got a "get" for
if (!verify_token(msg_keys[0]->string_value(), (char const*)&target[0], m.addr))
if (!verify_token(msg_keys[0].string_value(), (char const*)&target[0], m.addr))
{
m_counters.inc_stats_counter(counters::dht_invalid_put);
incoming_error(e, "invalid token");
@ -1133,12 +1141,12 @@ void node_impl::incoming_request(msg const& m, entry& e)
// mutable put, we must verify the signature
#ifdef TORRENT_USE_VALGRIND
VALGRIND_CHECK_MEM_IS_DEFINED(msg_keys[4]->string_ptr(), item_sig_len);
VALGRIND_CHECK_MEM_IS_DEFINED(msg_keys[4].string_ptr(), item_sig_len);
VALGRIND_CHECK_MEM_IS_DEFINED(pk, item_pk_len);
#endif
// msg_keys[4] is the signature, msg_keys[3] is the public key
if (!verify_mutable_item(buf, salt
, msg_keys[2]->int_value(), pk, sig))
, msg_keys[2].int_value(), pk, sig))
{
m_counters.inc_stats_counter(counters::dht_invalid_put);
incoming_error(e, "invalid signature", 206);
@ -1167,7 +1175,7 @@ void node_impl::incoming_request(msg const& m, entry& e)
dht_mutable_item to_add;
to_add.value = (char*)malloc(buf.second);
to_add.size = buf.second;
to_add.seq = msg_keys[2]->int_value();
to_add.seq = msg_keys[2].int_value();
to_add.salt = NULL;
to_add.salt_size = 0;
if (salt.second > 0)
@ -1177,7 +1185,7 @@ void node_impl::incoming_request(msg const& m, entry& e)
memcpy(to_add.salt, salt.first, salt.second);
}
memcpy(to_add.sig, sig, sizeof(to_add.sig));
TORRENT_ASSERT(sizeof(to_add.sig) == msg_keys[4]->string_length());
TORRENT_ASSERT(sizeof(to_add.sig) == msg_keys[4].string_length());
memcpy(to_add.value, buf.first, buf.second);
memcpy(&to_add.key, pk, sizeof(to_add.key));
@ -1197,21 +1205,21 @@ void node_impl::incoming_request(msg const& m, entry& e)
// number matches the expected value before replacing it
// this is critical for avoiding race conditions when multiple
// writers are accessing the same slot
if (msg_keys[5] && item->seq != msg_keys[5]->int_value())
if (msg_keys[5] && item->seq != msg_keys[5].int_value())
{
m_counters.inc_stats_counter(counters::dht_invalid_put);
incoming_error(e, "CAS mismatch", 301);
return;
}
if (item->seq > boost::uint64_t(msg_keys[2]->int_value()))
if (item->seq > boost::uint64_t(msg_keys[2].int_value()))
{
m_counters.inc_stats_counter(counters::dht_invalid_put);
incoming_error(e, "old sequence number", 302);
return;
}
if (item->seq < boost::uint64_t(msg_keys[2]->int_value()))
if (item->seq < boost::uint64_t(msg_keys[2].int_value()))
{
if (item->size != buf.second)
{
@ -1219,9 +1227,9 @@ void node_impl::incoming_request(msg const& m, entry& e)
item->value = (char*)malloc(buf.second);
item->size = buf.second;
}
item->seq = msg_keys[2]->int_value();
memcpy(item->sig, msg_keys[4]->string_ptr(), sizeof(item->sig));
TORRENT_ASSERT(sizeof(item->sig) == msg_keys[4]->string_length());
item->seq = msg_keys[2].int_value();
memcpy(item->sig, msg_keys[4].string_ptr(), sizeof(item->sig));
TORRENT_ASSERT(sizeof(item->sig) == msg_keys[4].string_length());
memcpy(item->value, buf.first, buf.second);
}
}
@ -1242,17 +1250,17 @@ void node_impl::incoming_request(msg const& m, entry& e)
++f->num_announcers;
}
}
else if (strcmp(query, "get") == 0)
else if (query_len == 3 && memcmp(query, "get", 3) == 0)
{
key_desc_t msg_desc[] = {
{"seq", lazy_entry::int_t, 0, key_desc_t::optional},
{"target", lazy_entry::string_t, 20, 0},
{"seq", bdecode_node::int_t, 0, key_desc_t::optional},
{"target", bdecode_node::string_t, 20, 0},
};
// k is not used for now
// attempt to parse the message
lazy_entry const* msg_keys[2];
bdecode_node msg_keys[2];
if (!verify_message(arg_ent, msg_desc, msg_keys, 2, error_string
, sizeof(error_string)))
{
@ -1262,13 +1270,13 @@ void node_impl::incoming_request(msg const& m, entry& e)
}
m_counters.inc_stats_counter(counters::dht_get_in);
sha1_hash target(msg_keys[1]->string_ptr());
sha1_hash target(msg_keys[1].string_ptr());
// fprintf(stderr, "%s GET target: %s\n"
// , msg_keys[1] ? "mutable":"immutable"
// , to_hex(target.to_string()).c_str());
reply["token"] = generate_token(m.addr, msg_keys[1]->string_ptr());
reply["token"] = generate_token(m.addr, msg_keys[1].string_ptr());
nodes_t n;
// always return nodes as well as peers
@ -1294,7 +1302,7 @@ void node_impl::incoming_request(msg const& m, entry& e)
{
dht_mutable_item const& f = i->second;
reply["seq"] = f.seq;
if (!msg_keys[0] || boost::uint64_t(msg_keys[0]->int_value()) < f.seq)
if (!msg_keys[0] || boost::uint64_t(msg_keys[0].int_value()) < f.seq)
{
reply["v"] = bdecode(f.value, f.value + f.size);
reply["sig"] = std::string(f.sig, f.sig + sizeof(f.sig));
@ -1308,18 +1316,18 @@ void node_impl::incoming_request(msg const& m, entry& e)
// if we don't recognize the message but there's a
// 'target' or 'info_hash' in the arguments, treat it
// as find_node to be future compatible
lazy_entry const* target_ent = arg_ent->dict_find_string("target");
if (target_ent == 0 || target_ent->string_length() != 20)
bdecode_node target_ent = arg_ent.dict_find_string("target");
if (!target_ent || target_ent.string_length() != 20)
{
target_ent = arg_ent->dict_find_string("info_hash");
if (target_ent == 0 || target_ent->string_length() != 20)
target_ent = arg_ent.dict_find_string("info_hash");
if (!target_ent || target_ent.string_length() != 20)
{
incoming_error(e, "unknown message");
return;
}
}
sha1_hash target(target_ent->string_ptr());
sha1_hash target(target_ent.string_ptr());
nodes_t n;
// always return nodes as well as peers
m_table.find_node(target, n, 0);

View File

@ -324,13 +324,13 @@ bool rpc_manager::incoming(msg const& m, node_id* id, libtorrent::dht_settings c
<< std::endl;
#endif
lazy_entry const* ret_ent = m.message.dict_find_dict("r");
if (ret_ent == 0)
bdecode_node ret_ent = m.message.dict_find_dict("r");
if (!ret_ent)
{
// it may be an error
ret_ent = m.message.dict_find("e");
o->timeout();
if (ret_ent == NULL)
if (!ret_ent)
{
entry e;
incoming_error(e, "missing 'r' key");
@ -339,8 +339,8 @@ bool rpc_manager::incoming(msg const& m, node_id* id, libtorrent::dht_settings c
return false;
}
lazy_entry const* node_id_ent = ret_ent->dict_find_string("id");
if (node_id_ent == 0 || node_id_ent->string_length() != 20)
bdecode_node node_id_ent = ret_ent.dict_find_string("id");
if (!node_id_ent || node_id_ent.string_length() != 20)
{
o->timeout();
entry e;
@ -349,7 +349,7 @@ bool rpc_manager::incoming(msg const& m, node_id* id, libtorrent::dht_settings c
return false;
}
node_id nid = node_id(node_id_ent->string_ptr());
node_id nid = node_id(node_id_ent.string_ptr());
if (settings.enforce_node_id && !verify_id(nid, m.addr.address()))
{
o->timeout();

View File

@ -521,7 +521,7 @@ void traversal_algorithm::status(dht_lookup& l)
void traversal_observer::reply(msg const& m)
{
lazy_entry const* r = m.message.dict_find_dict("r");
bdecode_node r = m.message.dict_find_dict("r");
if (!r)
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
@ -532,20 +532,20 @@ void traversal_observer::reply(msg const& m)
}
#ifdef TORRENT_DHT_VERBOSE_LOGGING
lazy_entry const* nid = r->dict_find_string("id");
bdecode_node nid = r.dict_find_string("id");
TORRENT_LOG(traversal) << "[" << m_algorithm.get() << "] "
"RESPONSE id: " << to_hex(nid->string_value())
<< " invoke-count: " << m_algorithm->invoke_count()
"RESPONSE id: " << to_hex(nid.string_value())
<< " invoke-count: " << m_algorithm.invoke_count()
<< " addr: " << m.addr
<< " type: " << m_algorithm->name()
<< " type: " << m_algorithm.name()
;
#endif
// look for nodes
lazy_entry const* n = r->dict_find_string("nodes");
bdecode_node n = r.dict_find_string("nodes");
if (n)
{
char const* nodes = n->string_ptr();
char const* end = nodes + n->string_length();
char const* nodes = n.string_ptr();
char const* end = nodes + n.string_length();
while (end - nodes >= 26)
{
@ -556,8 +556,8 @@ void traversal_observer::reply(msg const& m)
}
}
lazy_entry const* id = r->dict_find_string("id");
if (!id || id->string_length() != 20)
bdecode_node id = r.dict_find_string("id");
if (!id || id.string_length() != 20)
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(traversal) << "[" << m_algorithm.get() << "] invalid id in response";
@ -567,7 +567,7 @@ void traversal_observer::reply(msg const& m)
// in case we didn't know the id of this peer when we sent the message to
// it. For instance if it's a bootstrap node.
set_id(node_id(id->string_ptr()));
set_id(node_id(id.string_ptr()));
}
void traversal_algorithm::abort()

View File

@ -30,8 +30,11 @@ POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TORRENT_NO_DEPRECATE
#include "libtorrent/config.hpp"
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/bdecode.hpp" // for error codes
#include <cstring>
#include <limits> // for numeric_limits
@ -70,40 +73,6 @@ namespace libtorrent
namespace { bool numeric(char c) { return c >= '0' && c <= '9'; } }
// fills in 'val' with what the string between start and the
// first occurance of the delimiter is interpreted as an int.
// return the pointer to the delimiter, or 0 if there is a
// parse error. val should be initialized to zero
char const* parse_int(char const* start, char const* end, char delimiter
, boost::int64_t& val, bdecode_errors::error_code_enum& ec)
{
while (start < end && *start != delimiter)
{
if (!numeric(*start))
{
ec = bdecode_errors::expected_string;
return start;
}
if (val > (std::numeric_limits<boost::int64_t>::max)() / 10)
{
ec = bdecode_errors::overflow;
return start;
}
val *= 10;
int digit = *start - '0';
if (val > (std::numeric_limits<boost::int64_t>::max)() - digit)
{
ec = bdecode_errors::overflow;
return start;
}
val += digit;
++start;
}
if (*start != delimiter)
ec = bdecode_errors::expected_colon;
return start;
}
char const* find_char(char const* start, char const* end, char delimiter)
{
while (start < end && *start != delimiter) ++start;
@ -153,7 +122,7 @@ namespace libtorrent
stack.pop_back();
continue;
}
if (!numeric(t)) TORRENT_FAIL_BDECODE(bdecode_errors::expected_string);
if (!numeric(t)) TORRENT_FAIL_BDECODE(bdecode_errors::expected_digit);
boost::int64_t len = t - '0';
bdecode_errors::error_code_enum e = bdecode_errors::no_error;
start = parse_int(start, end, ':', len, e);
@ -382,7 +351,8 @@ namespace libtorrent
return e;
}
boost::int64_t lazy_entry::dict_find_int_value(char const* name, boost::int64_t default_val) const
boost::int64_t lazy_entry::dict_find_int_value(char const* name
, boost::int64_t default_val) const
{
lazy_entry const* e = dict_find(name);
if (e == 0 || e->type() != lazy_entry::int_t) return default_val;
@ -672,50 +642,7 @@ namespace libtorrent
}
return ret;
}
struct bdecode_error_category : boost::system::error_category
{
virtual const char* name() const BOOST_SYSTEM_NOEXCEPT;
virtual std::string message(int ev) const BOOST_SYSTEM_NOEXCEPT;
virtual boost::system::error_condition default_error_condition(int ev) const BOOST_SYSTEM_NOEXCEPT
{ return boost::system::error_condition(ev, *this); }
};
const char* bdecode_error_category::name() const BOOST_SYSTEM_NOEXCEPT
{
return "bdecode error";
}
std::string bdecode_error_category::message(int ev) const BOOST_SYSTEM_NOEXCEPT
{
static char const* msgs[] =
{
"no error",
"expected string in bencoded string",
"expected colon in bencoded string",
"unexpected end of file in bencoded string",
"expected value (list, dict, int or string) in bencoded string",
"bencoded nesting depth exceeded",
"bencoded item count limit exceeded",
"integer overflow",
};
if (ev < 0 || ev >= int(sizeof(msgs)/sizeof(msgs[0])))
return "Unknown error";
return msgs[ev];
}
boost::system::error_category& get_bdecode_category()
{
static bdecode_error_category bdecode_category;
return bdecode_category;
}
namespace bdecode_errors
{
boost::system::error_code make_error_code(error_code_enum e)
{
return boost::system::error_code(e, get_bdecode_category());
}
}
};
#endif // TORRENT_NO_DEPRECATE

View File

@ -167,14 +167,14 @@ namespace libtorrent { namespace
}
// called when the extension handshake from the other end is received
virtual bool on_extension_handshake(lazy_entry const& h)
virtual bool on_extension_handshake(bdecode_node const& h)
{
m_message_index = 0;
if (h.type() != lazy_entry::dict_t) return false;
lazy_entry const* messages = h.dict_find("m");
if (!messages || messages->type() != lazy_entry::dict_t) return false;
if (h.type() != bdecode_node::dict_t) return false;
bdecode_node messages = h.dict_find("m");
if (!messages || messages.type() != bdecode_node::dict_t) return false;
int index = int(messages->dict_find_int_value("lt_tex", -1));
int index = int(messages.dict_find_int_value("lt_tex", -1));
if (index == -1) return false;
m_message_index = index;
@ -196,16 +196,16 @@ namespace libtorrent { namespace
if (m_message_index == 0) return false;
if (!m_pc.packet_finished()) return true;
lazy_entry msg;
bdecode_node msg;
error_code ec;
int ret = lazy_bdecode(body.begin, body.end, msg, ec);
if (ret != 0 || msg.type() != lazy_entry::dict_t)
int ret = bdecode(body.begin, body.end, msg, ec);
if (ret != 0 || msg.type() != bdecode_node::dict_t)
{
m_pc.disconnect(errors::invalid_lt_tracker_message, op_bittorrent, 2);
return true;
}
lazy_entry const* added = msg.dict_find_list("added");
bdecode_node added = msg.dict_find_list("added");
// invalid tex message
if (added == 0)
@ -231,9 +231,9 @@ namespace libtorrent { namespace
"added: ";
#endif
for (int i = 0; i < added->list_size(); ++i)
for (int i = 0; i < added.list_size(); ++i)
{
announce_entry e(added->list_string_value_at(i));
announce_entry e(added.list_string_value_at(i));
if (e.url.empty()) continue;
// ignore urls with binary data in them

View File

@ -277,14 +277,14 @@ namespace libtorrent { namespace
}
// called when the extension handshake from the other end is received
virtual bool on_extension_handshake(lazy_entry const& h)
virtual bool on_extension_handshake(bdecode_node const& h)
{
m_message_index = 0;
if (h.type() != lazy_entry::dict_t) return false;
lazy_entry const* messages = h.dict_find("m");
if (!messages || messages->type() != lazy_entry::dict_t) return false;
if (h.type() != bdecode_node::dict_t) return false;
bdecode_node messages = h.dict_find("m");
if (!messages || messages.type() != bdecode_node::dict_t) return false;
int index = int(messages->dict_find_int_value("LT_metadata", -1));
int index = int(messages.dict_find_int_value("LT_metadata", -1));
if (index == -1) return false;
m_message_index = index;
return true;

View File

@ -398,31 +398,31 @@ void feed::on_feed(error_code const& ec
m_ses.update_rss_feeds();
}
void feed::load_state(lazy_entry const& rd)
void feed::load_state(bdecode_node const& rd)
{
m_title = rd.dict_find_string_value("m_title");
m_description = rd.dict_find_string_value("m_description");
m_last_attempt = rd.dict_find_int_value("m_last_attempt");
m_last_update = rd.dict_find_int_value("m_last_update");
lazy_entry const* e = rd.dict_find_list("items");
bdecode_node e = rd.dict_find_list("items");
if (e)
{
m_items.reserve(e->list_size());
for (int i = 0; i < e->list_size(); ++i)
m_items.reserve(e.list_size());
for (int i = 0; i < e.list_size(); ++i)
{
lazy_entry const* entry = e->list_at(i);
if (entry->type() != lazy_entry::dict_t) continue;
bdecode_node entry = e.list_at(i);
if (entry.type() != bdecode_node::dict_t) continue;
m_items.push_back(feed_item());
feed_item& item = m_items.back();
item.url = entry->dict_find_string_value("url");
item.uuid = entry->dict_find_string_value("uuid");
item.title = entry->dict_find_string_value("title");
item.description = entry->dict_find_string_value("description");
item.comment = entry->dict_find_string_value("comment");
item.category = entry->dict_find_string_value("category");
item.size = entry->dict_find_int_value("size");
item.url = entry.dict_find_string_value("url");
item.uuid = entry.dict_find_string_value("uuid");
item.title = entry.dict_find_string_value("title");
item.description = entry.dict_find_string_value("description");
item.comment = entry.dict_find_string_value("comment");
item.category = entry.dict_find_string_value("category");
item.size = entry.dict_find_int_value("size");
// don't load duplicates
if (m_urls.find(item.url) != m_urls.end())
@ -442,27 +442,27 @@ void feed::load_state(lazy_entry const& rd)
e = rd.dict_find_dict("add_params");
if (e)
{
m_settings.add_args.save_path = e->dict_find_string_value("save_path");
m_settings.add_args.flags = e->dict_find_int_value("flags");
m_settings.add_args.save_path = e.dict_find_string_value("save_path");
m_settings.add_args.flags = e.dict_find_int_value("flags");
}
e = rd.dict_find_list("history");
if (e)
{
for (int i = 0; i < e->list_size(); ++i)
for (int i = 0; i < e.list_size(); ++i)
{
if (e->list_at(i)->type() != lazy_entry::list_t) continue;
if (e.list_at(i).type() != bdecode_node::list_t) continue;
lazy_entry const* item = e->list_at(i);
bdecode_node item = e.list_at(i);
if (item->list_size() != 2
|| item->list_at(0)->type() != lazy_entry::string_t
|| item->list_at(1)->type() != lazy_entry::int_t)
if (item.list_size() != 2
|| item.list_at(0).type() != bdecode_node::string_t
|| item.list_at(1).type() != bdecode_node::int_t)
continue;
m_added.insert(std::pair<std::string, time_t>(
item->list_at(0)->string_value()
, item->list_at(1)->int_value()));
item.list_at(0).string_value()
, item.list_at(1).int_value()));
}
}
}

View File

@ -433,7 +433,7 @@ namespace libtorrent
TORRENT_SYNC_CALL2(save_state, &e, flags);
}
void session::load_state(lazy_entry const& e)
void session::load_state(bdecode_node const& e)
{
// this needs to be synchronized since the lifespan
// of e is tied to the caller
@ -494,12 +494,30 @@ namespace libtorrent
if (ses_state.type() == entry::undefined_t) return;
std::vector<char> buf;
bencode(std::back_inserter(buf), ses_state);
lazy_entry e;
bdecode_node e;
error_code ec;
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS || !defined BOOST_NO_EXCEPTIONS
int ret =
#endif
lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec);
bdecode(&buf[0], &buf[0] + buf.size(), e, ec);
TORRENT_ASSERT(ret == 0);
#ifndef BOOST_NO_EXCEPTIONS
if (ret != 0) throw libtorrent_exception(ec);
#endif
TORRENT_SYNC_CALL1(load_state, &e);
}
void session::load_state(lazy_entry const& ses_state)
{
if (ses_state.type() == lazy_entry::none_t) return;
std::pair<char const*, int> buf = ses_state.data_section();
bdecode_node e;
error_code ec;
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS || !defined BOOST_NO_EXCEPTIONS
int ret =
#endif
bdecode(buf.first, buf.first + buf.second, e, ec);
TORRENT_ASSERT(ret == 0);
#ifndef BOOST_NO_EXCEPTIONS

View File

@ -740,35 +740,35 @@ namespace aux {
return proxy_settings(m_settings);
}
void session_impl::load_state(lazy_entry const* e)
void session_impl::load_state(bdecode_node const* e)
{
TORRENT_ASSERT(is_single_thread());
lazy_entry const* settings;
if (e->type() != lazy_entry::dict_t) return;
bdecode_node settings;
if (e->type() != bdecode_node::dict_t) return;
#ifndef TORRENT_DISABLE_DHT
// load from the old settings names
settings = e->dict_find_dict("dht");
if (settings)
{
lazy_entry const* val;
val = settings->dict_find_int("max_peers_reply");
if (val) m_dht_settings.max_peers_reply = val->int_value();
val = settings->dict_find_int("search_branching");
if (val) m_dht_settings.search_branching = val->int_value();
val = settings->dict_find_int("max_fail_count");
if (val) m_dht_settings.max_fail_count = val->int_value();
val = settings->dict_find_int("max_torrents");
if (val) m_dht_settings.max_torrents = val->int_value();
val = settings->dict_find_int("max_dht_items");
if (val) m_dht_settings.max_dht_items = val->int_value();
val = settings->dict_find_int("max_torrent_search_reply");
if (val) m_dht_settings.max_torrent_search_reply = val->int_value();
val = settings->dict_find_int("restrict_routing_ips");
if (val) m_dht_settings.restrict_routing_ips = val->int_value();
val = settings->dict_find_int("extended_routing_table");
if (val) m_dht_settings.extended_routing_table = val->int_value();
bdecode_node val;
val = settings.dict_find_int("max_peers_reply");
if (val) m_dht_settings.max_peers_reply = val.int_value();
val = settings.dict_find_int("search_branching");
if (val) m_dht_settings.search_branching = val.int_value();
val = settings.dict_find_int("max_fail_count");
if (val) m_dht_settings.max_fail_count = val.int_value();
val = settings.dict_find_int("max_torrents");
if (val) m_dht_settings.max_torrents = val.int_value();
val = settings.dict_find_int("max_dht_items");
if (val) m_dht_settings.max_dht_items = val.int_value();
val = settings.dict_find_int("max_torrent_search_reply");
if (val) m_dht_settings.max_torrent_search_reply = val.int_value();
val = settings.dict_find_int("restrict_routing_ips");
if (val) m_dht_settings.restrict_routing_ips = val.int_value();
val = settings.dict_find_int("extended_routing_table");
if (val) m_dht_settings.extended_routing_table = val.int_value();
}
#endif
@ -776,35 +776,35 @@ namespace aux {
settings = e->dict_find_dict("proxy");
if (settings)
{
lazy_entry const* val;
val = settings->dict_find_int("port");
if (val) m_settings.set_int(settings_pack::proxy_port, val->int_value());
val = settings->dict_find_int("type");
if (val) m_settings.set_int(settings_pack::proxy_type, val->int_value());
val = settings->dict_find_int("proxy_hostnames");
if (val) m_settings.set_bool(settings_pack::proxy_hostnames, val->int_value());
val = settings->dict_find_int("proxy_peer_connections");
if (val) m_settings.set_bool(settings_pack::proxy_peer_connections, val->int_value());
val = settings->dict_find_string("hostname");
if (val) m_settings.set_str(settings_pack::proxy_hostname, val->string_value());
val = settings->dict_find_string("password");
if (val) m_settings.set_str(settings_pack::proxy_password, val->string_value());
val = settings->dict_find_string("username");
if (val) m_settings.set_str(settings_pack::proxy_username, val->string_value());
bdecode_node val;
val = settings.dict_find_int("port");
if (val) m_settings.set_int(settings_pack::proxy_port, val.int_value());
val = settings.dict_find_int("type");
if (val) m_settings.set_int(settings_pack::proxy_type, val.int_value());
val = settings.dict_find_int("proxy_hostnames");
if (val) m_settings.set_bool(settings_pack::proxy_hostnames, val.int_value());
val = settings.dict_find_int("proxy_peer_connections");
if (val) m_settings.set_bool(settings_pack::proxy_peer_connections, val.int_value());
val = settings.dict_find_string("hostname");
if (val) m_settings.set_str(settings_pack::proxy_hostname, val.string_value());
val = settings.dict_find_string("password");
if (val) m_settings.set_str(settings_pack::proxy_password, val.string_value());
val = settings.dict_find_string("username");
if (val) m_settings.set_str(settings_pack::proxy_username, val.string_value());
}
settings = e->dict_find_dict("encryption");
if (settings)
{
lazy_entry const* val;
val = settings->dict_find_int("prefer_rc4");
if (val) m_settings.set_bool(settings_pack::prefer_rc4, val->int_value());
val = settings->dict_find_int("out_enc_policy");
if (val) m_settings.set_int(settings_pack::out_enc_policy, val->int_value());
val = settings->dict_find_int("in_enc_policy");
if (val) m_settings.set_int(settings_pack::in_enc_policy, val->int_value());
val = settings->dict_find_int("allowed_enc_level");
if (val) m_settings.set_int(settings_pack::allowed_enc_level, val->int_value());
bdecode_node val;
val = settings.dict_find_int("prefer_rc4");
if (val) m_settings.set_bool(settings_pack::prefer_rc4, val.int_value());
val = settings.dict_find_int("out_enc_policy");
if (val) m_settings.set_int(settings_pack::out_enc_policy, val.int_value());
val = settings.dict_find_int("in_enc_policy");
if (val) m_settings.set_int(settings_pack::in_enc_policy, val.int_value());
val = settings.dict_find_int("allowed_enc_level");
if (val) m_settings.set_int(settings_pack::allowed_enc_level, val.int_value());
}
#endif
@ -824,19 +824,19 @@ namespace aux {
settings = e->dict_find_dict("dht state");
if (settings)
{
m_dht_state = *settings;
m_dht_state = settings;
}
#endif
settings = e->dict_find_list("feeds");
if (settings)
{
m_feeds.reserve(settings->list_size());
for (int i = 0; i < settings->list_size(); ++i)
m_feeds.reserve(settings.list_size());
for (int i = 0; i < settings.list_size(); ++i)
{
if (settings->list_at(i)->type() != lazy_entry::dict_t) continue;
if (settings.list_at(i).type() != bdecode_node::dict_t) continue;
boost::shared_ptr<feed> f(new_feed(*this, feed_settings()));
f->load_state(*settings->list_at(i));
f->load_state(settings.list_at(i));
f->update_feed();
m_feeds.push_back(f);
}
@ -4542,14 +4542,14 @@ retry:
{
int pos;
error_code ec;
lazy_entry tmp;
lazy_entry const* info = 0;
bdecode_node tmp;
bdecode_node info;
#if defined TORRENT_LOGGING
session_log("adding magnet link with resume data");
#endif
if (lazy_bdecode(&params.resume_data[0], &params.resume_data[0]
if (bdecode(&params.resume_data[0], &params.resume_data[0]
+ params.resume_data.size(), tmp, ec, &pos) == 0
&& tmp.type() == lazy_entry::dict_t
&& tmp.type() == bdecode_node::dict_t
&& (info = tmp.dict_find_dict("info")))
{
#if defined TORRENT_LOGGING
@ -4558,7 +4558,7 @@ retry:
// verify the info-hash of the metadata stored in the resume file matches
// the torrent we're loading
std::pair<char const*, int> buf = info->data_section();
std::pair<char const*, int> buf = info.data_section();
sha1_hash resume_ih = hasher(buf.first, buf.second).final();
// if url is set, the info_hash is not actually the info-hash of the
@ -4573,7 +4573,7 @@ retry:
#endif
params.ti = boost::make_shared<torrent_info>(resume_ih);
if (params.ti->parse_info_section(*info, ec, 0))
if (params.ti->parse_info_section(info, ec, 0))
{
#if defined TORRENT_LOGGING
session_log("successfully loaded metadata from resume file");

View File

@ -386,27 +386,27 @@ namespace libtorrent
return "";
}
settings_pack* load_pack_from_dict(lazy_entry const* settings)
settings_pack* load_pack_from_dict(bdecode_node const& settings)
{
settings_pack* pack = new settings_pack;
for (int i = 0; i < settings->dict_size(); ++i)
for (int i = 0; i < settings.dict_size(); ++i)
{
std::string key;
lazy_entry const* val;
boost::tie(key, val) = settings->dict_at(i);
switch (val->type())
bdecode_node val;
boost::tie(key, val) = settings.dict_at(i);
switch (val.type())
{
case lazy_entry::dict_t:
case lazy_entry::list_t:
case bdecode_node::dict_t:
case bdecode_node::list_t:
continue;
case lazy_entry::int_t:
case bdecode_node::int_t:
{
bool found = false;
for (int k = 0; k < sizeof(int_settings)/sizeof(int_settings[0]); ++k)
{
if (key != int_settings[k].name) continue;
pack->set_int(settings_pack::int_type_base + k, val->int_value());
pack->set_int(settings_pack::int_type_base + k, val.int_value());
found = true;
break;
}
@ -414,20 +414,20 @@ namespace libtorrent
for (int k = 0; k < sizeof(bool_settings)/sizeof(bool_settings[0]); ++k)
{
if (key != bool_settings[k].name) continue;
pack->set_bool(settings_pack::bool_type_base + k, val->int_value());
pack->set_bool(settings_pack::bool_type_base + k, val.int_value());
break;
}
}
break;
case lazy_entry::string_t:
case bdecode_node::string_t:
for (int k = 0; k < sizeof(str_settings)/sizeof(str_settings[0]); ++k)
{
if (key != str_settings[k].name) continue;
pack->set_str(settings_pack::string_type_base + k, val->string_value());
pack->set_str(settings_pack::string_type_base + k, val.string_value());
break;
}
break;
case lazy_entry::none_t:
case bdecode_node::none_t:
break;
}
}

View File

@ -712,47 +712,47 @@ namespace libtorrent
return int((data_start + files().piece_length() - 1) / files().piece_length());
}
bool default_storage::verify_resume_data(lazy_entry const& rd, storage_error& ec)
bool default_storage::verify_resume_data(bdecode_node const& rd, storage_error& ec)
{
// TODO: make this more generic to not just work if files have been
// renamed, but also if they have been merged into a single file for instance
// maybe use the same format as .torrent files and reuse some code from torrent_info
lazy_entry const* mapped_files = rd.dict_find_list("mapped_files");
if (mapped_files && mapped_files->list_size() == m_files.num_files())
bdecode_node mapped_files = rd.dict_find_list("mapped_files");
if (mapped_files && mapped_files.list_size() == m_files.num_files())
{
m_mapped_files.reset(new file_storage(m_files));
for (int i = 0; i < m_files.num_files(); ++i)
{
std::string new_filename = mapped_files->list_string_value_at(i);
std::string new_filename = mapped_files.list_string_value_at(i);
if (new_filename.empty()) continue;
m_mapped_files->rename_file(i, new_filename);
}
}
lazy_entry const* file_priority = rd.dict_find_list("file_priority");
if (file_priority && file_priority->list_size()
bdecode_node file_priority = rd.dict_find_list("file_priority");
if (file_priority && file_priority.list_size()
== files().num_files())
{
m_file_priority.resize(file_priority->list_size());
for (int i = 0; i < file_priority->list_size(); ++i)
m_file_priority[i] = boost::uint8_t(file_priority->list_int_value_at(i, 1));
m_file_priority.resize(file_priority.list_size());
for (int i = 0; i < file_priority.list_size(); ++i)
m_file_priority[i] = boost::uint8_t(file_priority.list_int_value_at(i, 1));
}
lazy_entry const* file_sizes_ent = rd.dict_find_list("file sizes");
bdecode_node file_sizes_ent = rd.dict_find_list("file sizes");
if (file_sizes_ent == 0)
{
ec.ec = errors::missing_file_sizes;
return false;
}
if (file_sizes_ent->list_size() == 0)
if (file_sizes_ent.list_size() == 0)
{
ec.ec = errors::no_files_in_resume_data;
return false;
}
file_storage const& fs = files();
if (file_sizes_ent->list_size() != fs.num_files())
if (file_sizes_ent.list_size() != fs.num_files())
{
ec.ec = errors::mismatching_number_of_files;
ec.file = -1;
@ -761,27 +761,27 @@ namespace libtorrent
}
bool seed = false;
lazy_entry const* slots = rd.dict_find_list("slots");
bdecode_node slots = rd.dict_find_list("slots");
if (slots)
{
if (int(slots->list_size()) == m_files.num_pieces())
if (int(slots.list_size()) == m_files.num_pieces())
{
seed = true;
for (int i = 0; i < slots->list_size(); ++i)
for (int i = 0; i < slots.list_size(); ++i)
{
if (slots->list_int_value_at(i, -1) >= 0) continue;
if (slots.list_int_value_at(i, -1) >= 0) continue;
seed = false;
break;
}
}
}
else if (lazy_entry const* pieces = rd.dict_find_string("pieces"))
else if (bdecode_node pieces = rd.dict_find_string("pieces"))
{
if (int(pieces->string_length()) == m_files.num_pieces())
if (int(pieces.string_length()) == m_files.num_pieces())
{
seed = true;
char const* p = pieces->string_ptr();
for (int i = 0; i < pieces->string_length(); ++i)
char const* p = pieces.string_ptr();
for (int i = 0; i < pieces.string_length(); ++i)
{
if ((p[i] & 1) == 1) continue;
seed = false;
@ -795,14 +795,14 @@ namespace libtorrent
return false;
}
for (int i = 0; i < file_sizes_ent->list_size(); ++i)
for (int i = 0; i < file_sizes_ent.list_size(); ++i)
{
if (fs.pad_file_at(i)) continue;
lazy_entry const* e = file_sizes_ent->list_at(i);
if (e->type() != lazy_entry::list_t
|| e->list_size() < 2
|| e->list_at(0)->type() != lazy_entry::int_t
|| e->list_at(1)->type() != lazy_entry::int_t)
bdecode_node e = file_sizes_ent.list_at(i);
if (e.type() != bdecode_node::list_t
|| e.list_size() < 2
|| e.list_at(0).type() != bdecode_node::int_t
|| e.list_at(1).type() != bdecode_node::int_t)
{
ec.ec = errors::missing_file_sizes;
ec.file = i;
@ -810,8 +810,8 @@ namespace libtorrent
return false;
}
boost::int64_t expected_size = e->list_int_value_at(0);
time_t expected_time = e->list_int_value_at(1);
boost::int64_t expected_size = e.list_int_value_at(0);
time_t expected_time = e.list_int_value_at(1);
// if we're a seed, the expected size should match
// the actual full size according to the torrent
@ -1472,14 +1472,14 @@ namespace libtorrent
// isn't return false and the full check
// will be run
int piece_manager::check_fastresume(
lazy_entry const& rd, storage_error& ec)
bdecode_node const& rd, storage_error& ec)
{
TORRENT_ASSERT(m_files.piece_length() > 0);
// if we don't have any resume data, return
if (rd.type() == lazy_entry::none_t) return check_no_fastresume(ec);
if (rd.type() == bdecode_node::none_t) return check_no_fastresume(ec);
if (rd.type() != lazy_entry::dict_t)
if (rd.type() != bdecode_node::dict_t)
{
ec.ec = errors::not_a_dictionary;
return check_no_fastresume(ec);

View File

@ -763,8 +763,8 @@ namespace libtorrent
{
int pos;
error_code ec;
if (lazy_bdecode(&m_resume_data->buf[0], &m_resume_data->buf[0]
+ m_resume_data->buf.size(), m_resume_data->entry, ec, &pos) != 0)
if (bdecode(&m_resume_data->buf[0], &m_resume_data->buf[0]
+ m_resume_data->buf.size(), m_resume_data->node, ec, &pos) != 0)
{
m_resume_data.reset();
#if defined TORRENT_LOGGING
@ -1745,13 +1745,16 @@ namespace libtorrent
return;
}
if (m_resume_data && m_resume_data->entry.type() == lazy_entry::dict_t)
if (m_resume_data && m_resume_data->node.type() == bdecode_node::dict_t)
{
int ev = 0;
if (m_resume_data->entry.dict_find_string_value("file-format") != "libtorrent resume file")
if (m_resume_data->node.dict_find_string_value("file-format")
!= "libtorrent resume file")
{
ev = errors::invalid_file_tag;
}
std::string info_hash = m_resume_data->entry.dict_find_string_value("info-hash");
std::string info_hash = m_resume_data->node.dict_find_string_value("info-hash");
if (!ev && info_hash.empty())
ev = errors::missing_info_hash;
@ -1774,7 +1777,7 @@ namespace libtorrent
}
else
{
read_resume_data(m_resume_data->entry);
read_resume_data(m_resume_data->node);
}
}
@ -1786,12 +1789,14 @@ namespace libtorrent
if (!m_seed_mode && m_resume_data)
{
lazy_entry const* piece_priority = m_resume_data->entry.dict_find_string("piece_priority");
if (piece_priority && piece_priority->string_length()
bdecode_node piece_priority = m_resume_data->node
.dict_find_string("piece_priority");
if (piece_priority && piece_priority.string_length()
== m_torrent_file->num_pieces())
{
char const* p = piece_priority->string_ptr();
for (int i = 0; i < piece_priority->string_length(); ++i)
char const* p = piece_priority.string_ptr();
for (int i = 0; i < piece_priority.string_length(); ++i)
{
int prio = p[i];
if (!has_picker() && prio == 1) continue;
@ -1924,7 +1929,7 @@ namespace libtorrent
inc_refcount("check_fastresume");
m_ses.disk_thread().async_check_fastresume(
m_storage.get(), m_resume_data ? &m_resume_data->entry : NULL
m_storage.get(), m_resume_data ? &m_resume_data->node : NULL
, boost::bind(&torrent::on_resume_data_checked
, shared_from_this(), _1));
#if defined TORRENT_LOGGING
@ -2146,14 +2151,14 @@ namespace libtorrent
state_updated();
if (m_resume_data && m_resume_data->entry.type() == lazy_entry::dict_t)
if (m_resume_data && m_resume_data->node.type() == bdecode_node::dict_t)
{
using namespace libtorrent::detail; // for read_*_endpoint()
if (lazy_entry const* peers_entry = m_resume_data->entry.dict_find_string("peers"))
if (bdecode_node peers_entry = m_resume_data->node.dict_find_string("peers"))
{
int num_peers = peers_entry->string_length() / (sizeof(address_v4::bytes_type) + 2);
char const* ptr = peers_entry->string_ptr();
int num_peers = peers_entry.string_length() / (sizeof(address_v4::bytes_type) + 2);
char const* ptr = peers_entry.string_ptr();
for (int i = 0; i < num_peers; ++i)
{
add_peer(read_v4_endpoint<tcp::endpoint>(ptr)
@ -2162,10 +2167,11 @@ namespace libtorrent
update_want_peers();
}
if (lazy_entry const* banned_peers_entry = m_resume_data->entry.dict_find_string("banned_peers"))
if (bdecode_node banned_peers_entry
= m_resume_data->node.dict_find_string("banned_peers"))
{
int num_peers = banned_peers_entry->string_length() / (sizeof(address_v4::bytes_type) + 2);
char const* ptr = banned_peers_entry->string_ptr();
int num_peers = banned_peers_entry.string_length() / (sizeof(address_v4::bytes_type) + 2);
char const* ptr = banned_peers_entry.string_ptr();
for (int i = 0; i < num_peers; ++i)
{
std::vector<torrent_peer*> peers;
@ -2178,10 +2184,10 @@ namespace libtorrent
}
#if TORRENT_USE_IPV6
if (lazy_entry const* peers6_entry = m_resume_data->entry.dict_find_string("peers6"))
if (bdecode_node peers6_entry = m_resume_data->node.dict_find_string("peers6"))
{
int num_peers = peers6_entry->string_length() / (sizeof(address_v6::bytes_type) + 2);
char const* ptr = peers6_entry->string_ptr();
int num_peers = peers6_entry.string_length() / (sizeof(address_v6::bytes_type) + 2);
char const* ptr = peers6_entry.string_ptr();
for (int i = 0; i < num_peers; ++i)
{
add_peer(read_v6_endpoint<tcp::endpoint>(ptr)
@ -2190,10 +2196,10 @@ namespace libtorrent
update_want_peers();
}
if (lazy_entry const* banned_peers6_entry = m_resume_data->entry.dict_find_string("banned_peers6"))
if (bdecode_node banned_peers6_entry = m_resume_data->node.dict_find_string("banned_peers6"))
{
int num_peers = banned_peers6_entry->string_length() / (sizeof(address_v6::bytes_type) + 2);
char const* ptr = banned_peers6_entry->string_ptr();
int num_peers = banned_peers6_entry.string_length() / (sizeof(address_v6::bytes_type) + 2);
char const* ptr = banned_peers6_entry.string_ptr();
for (int i = 0; i < num_peers; ++i)
{
torrent_peer* p = add_peer(read_v6_endpoint<tcp::endpoint>(ptr)
@ -2205,14 +2211,14 @@ namespace libtorrent
#endif
// parse out "peers" from the resume data and add them to the peer list
if (lazy_entry const* peers_entry = m_resume_data->entry.dict_find_list("peers"))
if (bdecode_node peers_entry = m_resume_data->node.dict_find_list("peers"))
{
for (int i = 0; i < peers_entry->list_size(); ++i)
for (int i = 0; i < peers_entry.list_size(); ++i)
{
lazy_entry const* e = peers_entry->list_at(i);
if (e->type() != lazy_entry::dict_t) continue;
std::string ip = e->dict_find_string_value("ip");
int port = e->dict_find_int_value("port");
bdecode_node e = peers_entry.list_at(i);
if (e.type() != bdecode_node::dict_t) continue;
std::string ip = e.dict_find_string_value("ip");
int port = e.dict_find_int_value("port");
if (ip.empty() || port == 0) continue;
error_code ec;
tcp::endpoint a(address::from_string(ip, ec), (unsigned short)port);
@ -2223,14 +2229,14 @@ namespace libtorrent
}
// parse out "banned_peers" and add them as banned
if (lazy_entry const* banned_peers_entry = m_resume_data->entry.dict_find_list("banned_peers"))
if (bdecode_node banned_peers_entry = m_resume_data->node.dict_find_list("banned_peers"))
{
for (int i = 0; i < banned_peers_entry->list_size(); ++i)
for (int i = 0; i < banned_peers_entry.list_size(); ++i)
{
lazy_entry const* e = banned_peers_entry->list_at(i);
if (e->type() != lazy_entry::dict_t) continue;
std::string ip = e->dict_find_string_value("ip");
int port = e->dict_find_int_value("port");
bdecode_node e = banned_peers_entry.list_at(i);
if (e.type() != bdecode_node::dict_t) continue;
std::string ip = e.dict_find_string_value("ip");
int port = e.dict_find_int_value("port");
if (ip.empty() || port == 0) continue;
error_code ec;
tcp::endpoint a(address::from_string(ip, ec), (unsigned short)port);
@ -2276,15 +2282,15 @@ namespace libtorrent
// there are either no files for this torrent
// or the resume_data was accepted
if (!j->error && m_resume_data && m_resume_data->entry.type() == lazy_entry::dict_t)
if (!j->error && m_resume_data && m_resume_data->node.type() == bdecode_node::dict_t)
{
// parse have bitmask
lazy_entry const* pieces = m_resume_data->entry.dict_find("pieces");
if (pieces && pieces->type() == lazy_entry::string_t
&& int(pieces->string_length()) == m_torrent_file->num_pieces())
bdecode_node pieces = m_resume_data->node.dict_find("pieces");
if (pieces && pieces.type() == bdecode_node::string_t
&& int(pieces.string_length()) == m_torrent_file->num_pieces())
{
char const* pieces_str = pieces->string_ptr();
for (int i = 0, end(pieces->string_length()); i < end; ++i)
char const* pieces_str = pieces.string_ptr();
for (int i = 0, end(pieces.string_length()); i < end; ++i)
{
if (pieces_str[i] & 1)
{
@ -2299,12 +2305,12 @@ namespace libtorrent
}
else
{
lazy_entry const* slots = m_resume_data->entry.dict_find("slots");
if (slots && slots->type() == lazy_entry::list_t)
bdecode_node slots = m_resume_data->node.dict_find("slots");
if (slots && slots.type() == bdecode_node::list_t)
{
for (int i = 0; i < slots->list_size(); ++i)
for (int i = 0; i < slots.list_size(); ++i)
{
int piece = slots->list_int_value_at(i, -1);
int piece = slots.list_int_value_at(i, -1);
if (piece >= 0)
{
need_picker();
@ -2321,13 +2327,14 @@ namespace libtorrent
int num_blocks_per_piece =
static_cast<int>(torrent_file().piece_length()) / block_size();
if (lazy_entry const* unfinished_ent = m_resume_data->entry.dict_find_list("unfinished"))
if (bdecode_node unfinished_ent
= m_resume_data->node.dict_find_list("unfinished"))
{
for (int i = 0; i < unfinished_ent->list_size(); ++i)
for (int i = 0; i < unfinished_ent.list_size(); ++i)
{
lazy_entry const* e = unfinished_ent->list_at(i);
if (e->type() != lazy_entry::dict_t) continue;
int piece = e->dict_find_int_value("piece", -1);
bdecode_node e = unfinished_ent.list_at(i);
if (e.type() != bdecode_node::dict_t) continue;
int piece = e.dict_find_int_value("piece", -1);
if (piece < 0 || piece > torrent_file().num_pieces()) continue;
if (has_picker() && m_picker->have_piece(piece))
@ -2336,7 +2343,7 @@ namespace libtorrent
update_gauge();
}
std::string bitmask = e->dict_find_string_value("bitmask");
std::string bitmask = e.dict_find_string_value("bitmask");
if (bitmask.empty()) continue;
need_picker();
@ -6534,7 +6541,7 @@ namespace libtorrent
}
#endif
void torrent::read_resume_data(lazy_entry const& rd)
void torrent::read_resume_data(bdecode_node const& rd)
{
m_total_uploaded = rd.dict_find_int_value("total_uploaded");
m_total_downloaded = rd.dict_find_int_value("total_downloaded");
@ -6627,12 +6634,12 @@ namespace libtorrent
// The mapped_files needs to be read both in the network thread
// and in the disk thread, since they both have their own mapped files structures
// which are kept in sync
lazy_entry const* mapped_files = rd.dict_find_list("mapped_files");
if (mapped_files && mapped_files->list_size() == m_torrent_file->num_files())
bdecode_node mapped_files = rd.dict_find_list("mapped_files");
if (mapped_files && mapped_files.list_size() == m_torrent_file->num_files())
{
for (int i = 0; i < m_torrent_file->num_files(); ++i)
{
std::string new_filename = mapped_files->list_string_value_at(i);
std::string new_filename = mapped_files.list_string_value_at(i);
if (new_filename.empty()) continue;
m_torrent_file->rename_file(i, new_filename);
}
@ -6645,14 +6652,14 @@ namespace libtorrent
if (!m_seed_mode && !m_override_resume_data)
{
lazy_entry const* file_priority = rd.dict_find_list("file_priority");
if (file_priority && file_priority->list_size()
bdecode_node file_priority = rd.dict_find_list("file_priority");
if (file_priority && file_priority.list_size()
== m_torrent_file->num_files())
{
int num_files = m_torrent_file->num_files();
m_file_priority.resize(num_files);
for (int i = 0; i < num_files; ++i)
m_file_priority[i] = file_priority->list_int_value_at(i, 1);
m_file_priority[i] = file_priority.list_int_value_at(i, 1);
// unallocated slots are assumed to be priority 1, so cut off any
// trailing ones
int end_range = num_files - 1;
@ -6671,19 +6678,19 @@ namespace libtorrent
update_piece_priorities();
}
lazy_entry const* trackers = rd.dict_find_list("trackers");
bdecode_node trackers = rd.dict_find_list("trackers");
if (trackers)
{
if (!m_merge_resume_trackers) m_trackers.clear();
int tier = 0;
for (int i = 0; i < trackers->list_size(); ++i)
for (int i = 0; i < trackers.list_size(); ++i)
{
lazy_entry const* tier_list = trackers->list_at(i);
if (tier_list == 0 || tier_list->type() != lazy_entry::list_t)
bdecode_node tier_list = trackers.list_at(i);
if (!tier_list || tier_list.type() != bdecode_node::list_t)
continue;
for (int j = 0; j < tier_list->list_size(); ++j)
for (int j = 0; j < tier_list.list_size(); ++j)
{
announce_entry e(tier_list->list_string_value_at(j));
announce_entry e(tier_list.list_string_value_at(j));
if (std::find_if(m_trackers.begin(), m_trackers.end()
, boost::bind(&announce_entry::url, _1) == e.url) != m_trackers.end())
continue;
@ -6700,24 +6707,24 @@ namespace libtorrent
prioritize_udp_trackers();
}
lazy_entry const* url_list = rd.dict_find_list("url-list");
bdecode_node url_list = rd.dict_find_list("url-list");
if (url_list)
{
for (int i = 0; i < url_list->list_size(); ++i)
for (int i = 0; i < url_list.list_size(); ++i)
{
std::string url = url_list->list_string_value_at(i);
std::string url = url_list.list_string_value_at(i);
if (url.empty()) continue;
if (m_torrent_file->num_files() > 1 && url[url.size()-1] != '/') url += '/';
add_web_seed(url, web_seed_entry::url_seed);
}
}
lazy_entry const* httpseeds = rd.dict_find_list("httpseeds");
bdecode_node httpseeds = rd.dict_find_list("httpseeds");
if (httpseeds)
{
for (int i = 0; i < httpseeds->list_size(); ++i)
for (int i = 0; i < httpseeds.list_size(); ++i)
{
std::string url = httpseeds->list_string_value_at(i);
std::string url = httpseeds.list_string_value_at(i);
if (url.empty()) continue;
add_web_seed(url, web_seed_entry::http_seed);
}
@ -6725,16 +6732,16 @@ namespace libtorrent
if (m_torrent_file->is_merkle_torrent())
{
lazy_entry const* mt = rd.dict_find_string("merkle tree");
bdecode_node mt = rd.dict_find_string("merkle tree");
if (mt)
{
std::vector<sha1_hash> tree;
tree.resize(m_torrent_file->merkle_tree().size());
std::memcpy(&tree[0], mt->string_ptr()
, (std::min)(mt->string_length(), int(tree.size()) * 20));
if (mt->string_length() < int(tree.size()) * 20)
std::memset(&tree[0] + mt->string_length() / 20, 0
, tree.size() - mt->string_length() / 20);
std::memcpy(&tree[0], mt.string_ptr()
, (std::min)(mt.string_length(), int(tree.size()) * 20));
if (mt.string_length() < int(tree.size()) * 20)
std::memset(&tree[0] + mt.string_length() / 20, 0
, tree.size() - mt.string_length() / 20);
m_torrent_file->set_merkle_tree(tree);
}
else
@ -7425,9 +7432,9 @@ namespace libtorrent
return false;
}
lazy_entry metadata;
bdecode_node metadata;
error_code ec;
int ret = lazy_bdecode(metadata_buf, metadata_buf + metadata_size, metadata, ec);
int ret = bdecode(metadata_buf, metadata_buf + metadata_size, metadata, ec);
if (ret != 0 || !m_torrent_file->parse_info_section(metadata, ec, 0))
{
update_gauge();
@ -8416,8 +8423,8 @@ namespace libtorrent
// this fires during disconnecting peers
// if (is_paused()) TORRENT_ASSERT(num_peers() == 0 || m_graceful_pause_mode);
TORRENT_ASSERT(!m_resume_data || m_resume_data->entry.type() == lazy_entry::dict_t
|| m_resume_data->entry.type() == lazy_entry::none_t);
TORRENT_ASSERT(!m_resume_data || m_resume_data->node.type() == bdecode_node::dict_t
|| m_resume_data->node.type() == bdecode_node::none_t);
int seeds = 0;
int num_uploads = 0;

View File

@ -54,6 +54,10 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/add_torrent_params.hpp"
#include "libtorrent/magnet_uri.hpp"
#ifndef TORRENT_NO_DEPRECATE
#include "libtorrent/lazy_entry.hpp"
#endif
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
@ -362,11 +366,11 @@ namespace libtorrent
// "path"
// root_dir is the name of the torrent, unless this is a single file
// torrent, in which case it's empty.
bool extract_single_file(lazy_entry const& dict, file_storage& files
bool extract_single_file(bdecode_node const& dict, file_storage& files
, std::string const& root_dir, ptrdiff_t info_ptr_diff, bool top_level
, error_code& ec)
{
if (dict.type() != lazy_entry::dict_t) return false;
if (dict.type() != bdecode_node::dict_t) return false;
boost::int64_t file_size = dict.dict_find_int_value("length", -1);
if (file_size < 0)
{
@ -385,52 +389,52 @@ namespace libtorrent
{
// prefer the name.utf-8 because if it exists, it is more likely to be
// correctly encoded
lazy_entry const* p = dict.dict_find_string("name.utf-8");
if (p == 0) p = dict.dict_find_string("name");
if (p == 0 || p->string_length() == 0)
bdecode_node p = dict.dict_find_string("name.utf-8");
if (!p) p = dict.dict_find_string("name");
if (!p || p.string_length() == 0)
{
ec = errors::torrent_missing_name;
return false;
}
filename = p->string_ptr() + info_ptr_diff;
filename_len = p->string_length();
sanitize_append_path_element(path, p->string_ptr(), p->string_length());
filename = p.string_ptr() + info_ptr_diff;
filename_len = p.string_length();
sanitize_append_path_element(path, p.string_ptr(), p.string_length());
// if (path.empty()) path = to_hex(files.info_hash().to_string());
}
else
{
lazy_entry const* p = dict.dict_find_list("path.utf-8");
if (p == 0) p = dict.dict_find_list("path");
if (p == 0 || p->list_size() == 0)
bdecode_node p = dict.dict_find_list("path.utf-8");
if (!p) p = dict.dict_find_list("path");
if (!p || p.list_size() == 0)
{
ec = errors::torrent_missing_name;
return false;
}
int preallocate = path.size();
for (int i = 0, end(p->list_size()); i < end; ++i)
for (int i = 0, end(p.list_size()); i < end; ++i)
{
lazy_entry const* e = p->list_at(i);
if (e->type() != lazy_entry::string_t)
bdecode_node e = p.list_at(i);
if (e.type() != bdecode_node::string_t)
{
ec = errors::torrent_missing_name;
return false;
}
preallocate += e->string_length() + 1;
preallocate += e.string_length() + 1;
}
path.reserve(preallocate);
for (int i = 0, end(p->list_size()); i < end; ++i)
for (int i = 0, end(p.list_size()); i < end; ++i)
{
lazy_entry const* e = p->list_at(i);
bdecode_node e = p.list_at(i);
if (i == end - 1)
{
filename = e->string_ptr() + info_ptr_diff;
filename_len = e->string_length();
filename = e.string_ptr() + info_ptr_diff;
filename_len = e.string_length();
}
sanitize_append_path_element(path, e->string_ptr(), e->string_length());
sanitize_append_path_element(path, e.string_ptr(), e.string_length());
}
}
@ -439,12 +443,12 @@ namespace libtorrent
if (path.find("_____padding_file_") != std::string::npos)
file_flags = file_storage::flag_pad_file;
lazy_entry const* attr = dict.dict_find_string("attr");
bdecode_node attr = dict.dict_find_string("attr");
if (attr)
{
for (int i = 0; i < attr->string_length(); ++i)
for (int i = 0; i < attr.string_length(); ++i)
{
switch (attr->string_ptr()[i])
switch (attr.string_ptr()[i])
{
case 'l': file_flags |= file_storage::flag_symlink; file_size = 0; break;
case 'x': file_flags |= file_storage::flag_executable; break;
@ -454,19 +458,19 @@ namespace libtorrent
}
}
lazy_entry const* fh = dict.dict_find_string("sha1");
bdecode_node fh = dict.dict_find_string("sha1");
char const* filehash = NULL;
if (fh && fh->string_length() == 20)
filehash = fh->string_ptr() + info_ptr_diff;
if (fh && fh.string_length() == 20)
filehash = fh.string_ptr() + info_ptr_diff;
std::string symlink_path;
lazy_entry const* s_p = dict.dict_find("symlink path");
if (s_p != 0 && s_p->type() == lazy_entry::list_t
bdecode_node s_p = dict.dict_find("symlink path");
if (s_p && s_p.type() == bdecode_node::list_t
&& (file_flags & file_storage::flag_symlink))
{
for (int i = 0, end(s_p->list_size()); i < end; ++i)
for (int i = 0, end(s_p.list_size()); i < end; ++i)
{
std::string path_element = s_p->list_at(i)->string_value();
std::string path_element = s_p.list_at(i).string_value();
symlink_path = combine_path(symlink_path, path_element);
}
}
@ -550,10 +554,10 @@ namespace libtorrent
// root_dir is the name of the torrent, unless this is a single file
// torrent, in which case it's empty.
bool extract_files(lazy_entry const& list, file_storage& target
bool extract_files(bdecode_node const& list, file_storage& target
, std::string const& root_dir, ptrdiff_t info_ptr_diff, error_code& ec)
{
if (list.type() != lazy_entry::list_t)
if (list.type() != bdecode_node::list_t)
{
ec = errors::torrent_file_parse_failed;
return false;
@ -562,7 +566,7 @@ namespace libtorrent
for (int i = 0, end(list.list_size()); i < end; ++i)
{
if (!extract_single_file(*list.list_at(i), target, root_dir
if (!extract_single_file(list.list_at(i), target, root_dir
, info_ptr_diff, false, ec))
return false;
}
@ -691,7 +695,7 @@ namespace libtorrent
// event, we need to let this announce through
bool need_send_complete = is_seed && !complete_sent;
return now >= next_announce
return now > next_announce
&& (now >= min_announce || need_send_complete)
&& (fails < fail_limit || fail_limit == 0)
&& !updating;
@ -735,6 +739,7 @@ namespace libtorrent
t.check_invariant();
#endif
if (m_info_section_size == 0) return;
TORRENT_ASSERT(m_piece_hashes);
error_code ec;
m_info_section.reset(new char[m_info_section_size]);
@ -746,15 +751,12 @@ namespace libtorrent
if (m_orig_files)
const_cast<file_storage&>(*m_orig_files).apply_pointer_offset(offset);
#if TORRENT_USE_ASSERTS || !defined BOOST_NO_EXCEPTIONS
int ret =
#endif
lazy_bdecode(m_info_section.get(), m_info_section.get()
+ m_info_section_size, m_info_dict, ec);
#ifndef BOOST_NO_EXCEPTIONS
if (ret != 0) throw libtorrent_exception(ec);
#endif
TORRENT_ASSERT(ret == 0);
if (m_info_dict)
{
// make this decoded object point to our copy of the info section
// buffer
m_info_dict.switch_underlying_buffer(m_info_section.get());
}
m_piece_hashes += offset;
TORRENT_ASSERT(m_piece_hashes >= m_info_section.get());
@ -861,6 +863,50 @@ namespace libtorrent
}
#ifndef TORRENT_NO_DEPRECATE
torrent_info::torrent_info(lazy_entry const& torrent_file, error_code& ec
, int flags)
: m_piece_hashes(0)
, m_creation_date(0)
, m_merkle_first_leaf(0)
, m_info_section_size(0)
, m_multifile(false)
, m_private(false)
, m_i2p(false)
{
std::pair<char const*, int> buf = torrent_file.data_section();
bdecode_node e;
if (bdecode(buf.first, buf.first + buf.second, e, ec) != 0)
return;
parse_torrent_file(e, ec, 0);
}
torrent_info::torrent_info(lazy_entry const& torrent_file, int flags)
: m_piece_hashes(0)
, m_creation_date(0)
, m_merkle_first_leaf(0)
, m_info_section_size(0)
, m_multifile(false)
, m_private(false)
, m_i2p(false)
{
std::pair<char const*, int> buf = torrent_file.data_section();
bdecode_node e;
error_code ec;
if (bdecode(buf.first, buf.first + buf.second, e, ec) != 0)
{
#ifndef BOOST_NO_EXCEPTIONS
throw invalid_torrent_file(ec);
#endif
return;
}
#ifndef BOOST_NO_EXCEPTIONS
if (!parse_torrent_file(e, ec, 0))
throw invalid_torrent_file(ec);
#else
parse_torrent_file(e, ec, 0);
#endif
}
// standard constructor that parses a torrent file
torrent_info::torrent_info(entry const& torrent_file)
: m_piece_hashes(0)
@ -875,9 +921,9 @@ namespace libtorrent
std::back_insert_iterator<std::vector<char> > out(tmp);
bencode(out, torrent_file);
lazy_entry e;
bdecode_node e;
error_code ec;
if (tmp.size() == 0 || lazy_bdecode(&tmp[0], &tmp[0] + tmp.size(), e, ec) != 0)
if (tmp.size() == 0 || bdecode(&tmp[0], &tmp[0] + tmp.size(), e, ec) != 0)
{
#ifndef BOOST_NO_EXCEPTIONS
throw invalid_torrent_file(ec);
@ -895,7 +941,7 @@ namespace libtorrent
#endif
#ifndef BOOST_NO_EXCEPTIONS
torrent_info::torrent_info(lazy_entry const& torrent_file, int flags)
torrent_info::torrent_info(bdecode_node const& torrent_file, int flags)
: m_piece_hashes(0)
, m_creation_date(0)
, m_merkle_first_leaf(0)
@ -921,8 +967,8 @@ namespace libtorrent
, m_i2p(false)
{
error_code ec;
lazy_entry e;
if (lazy_bdecode(buffer, buffer + size, e, ec) != 0)
bdecode_node e;
if (bdecode(buffer, buffer + size, e, ec) != 0)
throw invalid_torrent_file(ec);
if (!parse_torrent_file(e, ec, flags))
@ -945,8 +991,8 @@ namespace libtorrent
int ret = load_file(filename, buf, ec);
if (ret < 0) throw invalid_torrent_file(ec);
lazy_entry e;
if (buf.size() == 0 || lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec) != 0)
bdecode_node e;
if (buf.size() == 0 || bdecode(&buf[0], &buf[0] + buf.size(), e, ec) != 0)
throw invalid_torrent_file(ec);
if (!parse_torrent_file(e, ec, flags))
@ -973,8 +1019,8 @@ namespace libtorrent
int ret = load_file(utf8, buf, ec);
if (ret < 0) throw invalid_torrent_file(ec);
lazy_entry e;
if (buf.size() == 0 || lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec) != 0)
bdecode_node e;
if (buf.size() == 0 || bdecode(&buf[0], &buf[0] + buf.size(), e, ec) != 0)
throw invalid_torrent_file(ec);
if (!parse_torrent_file(e, ec, flags))
@ -993,7 +1039,7 @@ namespace libtorrent
#endif // TORRENT_USE_WSTRING
#endif
torrent_info::torrent_info(lazy_entry const& torrent_file, error_code& ec, int flags)
torrent_info::torrent_info(bdecode_node const& torrent_file, error_code& ec, int flags)
: m_piece_hashes(0)
, m_creation_date(0)
, m_merkle_first_leaf(0)
@ -1016,8 +1062,8 @@ namespace libtorrent
, m_private(false)
, m_i2p(false)
{
lazy_entry e;
if (lazy_bdecode(buffer, buffer + size, e, ec) != 0)
bdecode_node e;
if (bdecode(buffer, buffer + size, e, ec) != 0)
return;
parse_torrent_file(e, ec, flags);
@ -1037,8 +1083,8 @@ namespace libtorrent
int ret = load_file(filename, buf, ec);
if (ret < 0) return;
lazy_entry e;
if (buf.size() == 0 || lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec) != 0)
bdecode_node e;
if (buf.size() == 0 || bdecode(&buf[0], &buf[0] + buf.size(), e, ec) != 0)
return;
parse_torrent_file(e, ec, flags);
@ -1062,8 +1108,8 @@ namespace libtorrent
int ret = load_file(utf8, buf, ec);
if (ret < 0) return;
lazy_entry e;
if (buf.size() == 0 || lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec) != 0)
bdecode_node e;
if (buf.size() == 0 || bdecode(&buf[0], &buf[0] + buf.size(), e, ec) != 0)
return;
parse_torrent_file(e, ec, flags);
@ -1092,8 +1138,8 @@ namespace libtorrent
void torrent_info::load(char const* buffer, int size, error_code& ec)
{
lazy_entry e;
if (lazy_bdecode(buffer, buffer + size, e, ec) != 0)
bdecode_node e;
if (bdecode(buffer, buffer + size, e, ec) != 0)
return;
if (!parse_torrent_file(e, ec, 0))
@ -1166,20 +1212,21 @@ namespace libtorrent
std::string torrent_info::ssl_cert() const
{
// this is parsed lazily
if (m_info_dict.type() == lazy_entry::none_t)
if (!m_info_dict)
{
error_code ec;
lazy_bdecode(m_info_section.get(), m_info_section.get()
bdecode(m_info_section.get(), m_info_section.get()
+ m_info_section_size, m_info_dict, ec);
if (ec) return "";
}
if (m_info_dict.type() != lazy_entry::dict_t) return "";
if (m_info_dict.type() != bdecode_node::dict_t) return "";
return m_info_dict.dict_find_string_value("ssl-cert");
}
bool torrent_info::parse_info_section(lazy_entry const& info, error_code& ec, int flags)
bool torrent_info::parse_info_section(bdecode_node const& info
, error_code& ec, int flags)
{
if (info.type() != lazy_entry::dict_t)
if (info.type() != bdecode_node::dict_t)
{
ec = errors::torrent_info_no_dict;
return false;
@ -1214,22 +1261,23 @@ namespace libtorrent
files.set_piece_length(piece_length);
// extract file name (or the directory name if it's a multifile libtorrent)
lazy_entry const* name_ent = info.dict_find_string("name.utf-8");
if (name_ent == 0) name_ent = info.dict_find_string("name");
if (name_ent == 0)
bdecode_node name_ent = info.dict_find_string("name.utf-8");
if (!name_ent) name_ent = info.dict_find_string("name");
if (!name_ent)
{
ec = errors::torrent_missing_name;
return false;
}
std::string name;
sanitize_append_path_element(name, name_ent->string_ptr(), name_ent->string_length());
sanitize_append_path_element(name, name_ent.string_ptr()
, name_ent.string_length());
if (name.empty()) name = to_hex(m_info_hash.to_string());
// extract file list
lazy_entry const* i = info.dict_find_list("files");
if (i == 0)
bdecode_node i = info.dict_find_list("files");
if (!i)
{
// if there's no list of files, there has to be a length
// field.
@ -1240,7 +1288,7 @@ namespace libtorrent
}
else
{
if (!extract_files(*i, files, name, info_ptr_diff, ec))
if (!extract_files(i, files, name, info_ptr_diff, ec))
return false;
m_multifile = true;
}
@ -1253,9 +1301,9 @@ namespace libtorrent
files.set_num_pieces(int((files.total_size() + files.piece_length() - 1)
/ files.piece_length()));
lazy_entry const* pieces = info.dict_find_string("pieces");
lazy_entry const* root_hash = info.dict_find_string("root hash");
if (pieces == 0 && root_hash == 0)
bdecode_node pieces = info.dict_find_string("pieces");
bdecode_node root_hash = info.dict_find_string("root hash");
if (!pieces && !root_hash)
{
ec = errors::torrent_missing_pieces;
return false;
@ -1263,20 +1311,20 @@ namespace libtorrent
if (pieces)
{
if (pieces->string_length() != files.num_pieces() * 20)
if (pieces.string_length() != files.num_pieces() * 20)
{
ec = errors::torrent_invalid_hashes;
return false;
}
m_piece_hashes = pieces->string_ptr() + info_ptr_diff;
m_piece_hashes = pieces.string_ptr() + info_ptr_diff;
TORRENT_ASSERT(m_piece_hashes >= m_info_section.get());
TORRENT_ASSERT(m_piece_hashes < m_info_section.get() + m_info_section_size);
}
else
{
TORRENT_ASSERT(root_hash);
if (root_hash->string_length() != 20)
if (root_hash.string_length() != 20)
{
ec = errors::torrent_invalid_hashes;
return false;
@ -1286,7 +1334,7 @@ namespace libtorrent
m_merkle_first_leaf = num_nodes - num_leafs;
m_merkle_tree.resize(num_nodes);
std::memset(&m_merkle_tree[0], 0, num_nodes * 20);
m_merkle_tree[0].assign(root_hash->string_ptr());
m_merkle_tree[0].assign(root_hash.string_ptr());
}
m_private = info.dict_find_int_value("private", 0);
@ -1396,21 +1444,22 @@ namespace libtorrent
}
#endif
bool torrent_info::parse_torrent_file(lazy_entry const& torrent_file, error_code& ec, int flags)
bool torrent_info::parse_torrent_file(bdecode_node const& torrent_file
, error_code& ec, int flags)
{
if (torrent_file.type() != lazy_entry::dict_t)
if (torrent_file.type() != bdecode_node::dict_t)
{
ec = errors::torrent_is_no_dict;
return false;
}
lazy_entry const* info = torrent_file.dict_find_dict("info");
bdecode_node info = torrent_file.dict_find_dict("info");
if (info == 0)
{
lazy_entry const* link = torrent_file.dict_find_string("magnet-uri");
bdecode_node link = torrent_file.dict_find_string("magnet-uri");
if (link)
{
std::string uri = link->string_value();
std::string uri = link.string_value();
add_torrent_params p;
parse_magnet_uri(uri, p, ec);
@ -1427,21 +1476,21 @@ namespace libtorrent
ec = errors::torrent_missing_info;
return false;
}
if (!parse_info_section(*info, ec, flags)) return false;
if (!parse_info_section(info, ec, flags)) return false;
resolve_duplicate_filenames();
// extract the url of the tracker
lazy_entry const* i = torrent_file.dict_find_list("announce-list");
bdecode_node i = torrent_file.dict_find_list("announce-list");
if (i)
{
m_urls.reserve(i->list_size());
for (int j = 0, end(i->list_size()); j < end; ++j)
m_urls.reserve(i.list_size());
for (int j = 0, end(i.list_size()); j < end; ++j)
{
lazy_entry const* tier = i->list_at(j);
if (tier->type() != lazy_entry::list_t) continue;
for (int k = 0, end(tier->list_size()); k < end; ++k)
bdecode_node tier = i.list_at(j);
if (tier.type() != bdecode_node::list_t) continue;
for (int k = 0, end(tier.list_size()); k < end; ++k)
{
announce_entry e(tier->list_string_value_at(k));
announce_entry e(tier.list_string_value_at(k));
e.trim();
if (e.url.empty()) continue;
e.tier = j;
@ -1486,20 +1535,20 @@ namespace libtorrent
if (!e.url.empty()) m_urls.push_back(e);
}
lazy_entry const* nodes = torrent_file.dict_find_list("nodes");
bdecode_node nodes = torrent_file.dict_find_list("nodes");
if (nodes)
{
for (int i = 0, end(nodes->list_size()); i < end; ++i)
for (int i = 0, end(nodes.list_size()); i < end; ++i)
{
lazy_entry const* n = nodes->list_at(i);
if (n->type() != lazy_entry::list_t
|| n->list_size() < 2
|| n->list_at(0)->type() != lazy_entry::string_t
|| n->list_at(1)->type() != lazy_entry::int_t)
bdecode_node n = nodes.list_at(i);
if (n.type() != bdecode_node::list_t
|| n.list_size() < 2
|| n.list_at(0).type() != bdecode_node::string_t
|| n.list_at(1).type() != bdecode_node::int_t)
continue;
m_nodes.push_back(std::make_pair(
n->list_at(0)->string_value()
, int(n->list_at(1)->int_value())));
n.list_at(0).string_value()
, int(n.list_at(1).int_value())));
}
}
@ -1511,24 +1560,25 @@ namespace libtorrent
}
// if there are any url-seeds, extract them
lazy_entry const* url_seeds = torrent_file.dict_find("url-list");
if (url_seeds && url_seeds->type() == lazy_entry::string_t && url_seeds->string_length() > 0)
bdecode_node url_seeds = torrent_file.dict_find("url-list");
if (url_seeds && url_seeds.type() == bdecode_node::string_t
&& url_seeds.string_length() > 0)
{
web_seed_entry ent(maybe_url_encode(url_seeds->string_value())
web_seed_entry ent(maybe_url_encode(url_seeds.string_value())
, web_seed_entry::url_seed);
if (m_multifile && ent.url[ent.url.size()-1] != '/') ent.url += '/';
m_web_seeds.push_back(ent);
}
else if (url_seeds && url_seeds->type() == lazy_entry::list_t)
else if (url_seeds && url_seeds.type() == bdecode_node::list_t)
{
// only add a URL once
std::set<std::string> unique;
for (int i = 0, end(url_seeds->list_size()); i < end; ++i)
for (int i = 0, end(url_seeds.list_size()); i < end; ++i)
{
lazy_entry const* url = url_seeds->list_at(i);
if (url->type() != lazy_entry::string_t) continue;
if (url->string_length() == 0) continue;
web_seed_entry ent(maybe_url_encode(url->string_value())
bdecode_node url = url_seeds.list_at(i);
if (url.type() != bdecode_node::string_t) continue;
if (url.string_length() == 0) continue;
web_seed_entry ent(maybe_url_encode(url.string_value())
, web_seed_entry::url_seed);
if (m_multifile && ent.url[ent.url.size()-1] != '/') ent.url += '/';
if (unique.count(ent.url)) continue;
@ -1538,21 +1588,22 @@ namespace libtorrent
}
// if there are any http-seeds, extract them
lazy_entry const* http_seeds = torrent_file.dict_find("httpseeds");
if (http_seeds && http_seeds->type() == lazy_entry::string_t && http_seeds->string_length() > 0)
bdecode_node http_seeds = torrent_file.dict_find("httpseeds");
if (http_seeds && http_seeds.type() == bdecode_node::string_t
&& http_seeds.string_length() > 0)
{
m_web_seeds.push_back(web_seed_entry(maybe_url_encode(http_seeds->string_value())
m_web_seeds.push_back(web_seed_entry(maybe_url_encode(http_seeds.string_value())
, web_seed_entry::http_seed));
}
else if (http_seeds && http_seeds->type() == lazy_entry::list_t)
else if (http_seeds && http_seeds.type() == bdecode_node::list_t)
{
// only add a URL once
std::set<std::string> unique;
for (int i = 0, end(http_seeds->list_size()); i < end; ++i)
for (int i = 0, end(http_seeds.list_size()); i < end; ++i)
{
lazy_entry const* url = http_seeds->list_at(i);
if (url->type() != lazy_entry::string_t || url->string_length() == 0) continue;
std::string u = maybe_url_encode(url->string_value());
bdecode_node url = http_seeds.list_at(i);
if (url.type() != bdecode_node::string_t || url.string_length() == 0) continue;
std::string u = maybe_url_encode(url.string_value());
if (unique.count(u)) continue;
unique.insert(u);
m_web_seeds.push_back(web_seed_entry(u, web_seed_entry::http_seed));
@ -1616,6 +1667,18 @@ namespace libtorrent
, filter_web_seed_type(web_seed_entry::http_seed)).urls;
}
bool torrent_info::parse_info_section(lazy_entry const& le, error_code& ec
, int flags)
{
if (le.type() == lazy_entry::none_t) return false;
std::pair<char const*, int> buf = le.data_section();
bdecode_node e;
if (bdecode(buf.first, buf.first + buf.second, e, ec) != 0)
return false;
return parse_info_section(e, ec, flags);
}
#endif // TORRENT_NO_DEPRECATE
void torrent_info::add_url_seed(std::string const& url

View File

@ -234,14 +234,14 @@ namespace libtorrent { namespace
}
// called when the extension handshake from the other end is received
virtual bool on_extension_handshake(lazy_entry const& h)
virtual bool on_extension_handshake(bdecode_node const& h)
{
m_message_index = 0;
if (h.type() != lazy_entry::dict_t) return false;
lazy_entry const* messages = h.dict_find_dict("m");
if (h.type() != bdecode_node::dict_t) return false;
bdecode_node messages = h.dict_find_dict("m");
if (!messages) return false;
int index = messages->dict_find_int_value("ut_metadata", -1);
int index = messages.dict_find_int_value("ut_metadata", -1);
if (index == -1) return false;
m_message_index = index;

View File

@ -260,14 +260,14 @@ namespace libtorrent { namespace
messages[extension_name] = extension_index;
}
virtual bool on_extension_handshake(lazy_entry const& h)
virtual bool on_extension_handshake(bdecode_node const& h)
{
m_message_index = 0;
if (h.type() != lazy_entry::dict_t) return false;
lazy_entry const* messages = h.dict_find("m");
if (!messages || messages->type() != lazy_entry::dict_t) return false;
if (h.type() != bdecode_node::dict_t) return false;
bdecode_node messages = h.dict_find_dict("m");
if (!messages) return false;
int index = int(messages->dict_find_int_value(extension_name, -1));
int index = int(messages.dict_find_int_value(extension_name, -1));
if (index == -1) return false;
m_message_index = index;
return true;
@ -300,26 +300,26 @@ namespace libtorrent { namespace
m_last_pex[i] = m_last_pex[i+1];
m_last_pex[num_pex_timers-1] = now;
lazy_entry pex_msg;
bdecode_node pex_msg;
error_code ec;
int ret = lazy_bdecode(body.begin, body.end, pex_msg, ec);
if (ret != 0 || pex_msg.type() != lazy_entry::dict_t)
int ret = bdecode(body.begin, body.end, pex_msg, ec);
if (ret != 0 || pex_msg.type() != bdecode_node::dict_t)
{
m_pc.disconnect(errors::invalid_pex_message, op_bittorrent, 2);
return true;
}
lazy_entry const* p = pex_msg.dict_find_string("dropped");
bdecode_node p = pex_msg.dict_find_string("dropped");
#ifdef TORRENT_LOGGING
int num_dropped = 0;
int num_added = 0;
if (p) num_dropped += p->string_length()/6;
if (p) num_dropped += p.string_length()/6;
#endif
if (p)
{
int num_peers = p->string_length() / 6;
char const* in = p->string_ptr();
int num_peers = p.string_length() / 6;
char const* in = p.string_ptr();
for (int i = 0; i < num_peers; ++i)
{
@ -331,18 +331,16 @@ namespace libtorrent { namespace
}
p = pex_msg.dict_find_string("added");
lazy_entry const* pf = pex_msg.dict_find_string("added.f");
bdecode_node pf = pex_msg.dict_find_string("added.f");
#ifdef TORRENT_LOGGING
if (p) num_added += p->string_length() / 6;
if (p) num_added += p.string_length() / 6;
#endif
if (p != 0
&& pf != 0
&& pf->string_length() == p->string_length() / 6)
if (p && pf && pf.string_length() == p.string_length() / 6)
{
int num_peers = pf->string_length();
char const* in = p->string_ptr();
char const* fin = pf->string_ptr();
int num_peers = pf.string_length();
char const* in = p.string_ptr();
char const* fin = pf.string_ptr();
for (int i = 0; i < num_peers; ++i)
{
@ -366,14 +364,14 @@ namespace libtorrent { namespace
#if TORRENT_USE_IPV6
lazy_entry const* p6 = pex_msg.dict_find("dropped6");
bdecode_node p6 = pex_msg.dict_find("dropped6");
#ifdef TORRENT_LOGGING
if (p6) num_dropped += p6->string_length() / 18;
if (p6) num_dropped += p6.string_length() / 18;
#endif
if (p6 != 0 && p6->type() == lazy_entry::string_t)
if (p6 != 0 && p6.type() == bdecode_node::string_t)
{
int num_peers = p6->string_length() / 18;
char const* in = p6->string_ptr();
int num_peers = p6.string_length() / 18;
char const* in = p6.string_ptr();
for (int i = 0; i < num_peers; ++i)
{
@ -386,18 +384,18 @@ namespace libtorrent { namespace
p6 = pex_msg.dict_find("added6");
#ifdef TORRENT_LOGGING
if (p6) num_added += p6->string_length() / 18;
if (p6) num_added += p6.string_length() / 18;
#endif
lazy_entry const* p6f = pex_msg.dict_find("added6.f");
bdecode_node p6f = pex_msg.dict_find("added6.f");
if (p6 != 0
&& p6f != 0
&& p6->type() == lazy_entry::string_t
&& p6f->type() == lazy_entry::string_t
&& p6f->string_length() == p6->string_length() / 18)
&& p6.type() == bdecode_node::string_t
&& p6f.type() == bdecode_node::string_t
&& p6f.string_length() == p6.string_length() / 18)
{
int num_peers = p6f->string_length();
char const* in = p6->string_ptr();
char const* fin = p6f->string_ptr();
int num_peers = p6f.string_length();
char const* in = p6.string_ptr();
char const* fin = p6f.string_ptr();
for (int i = 0; i < num_peers; ++i)
{
@ -500,21 +498,21 @@ namespace libtorrent { namespace
m_pc.stats_counters().inc_stats_counter(counters::num_outgoing_pex);
#ifdef TORRENT_LOGGING
lazy_entry m;
bdecode_node m;
error_code ec;
int ret = lazy_bdecode(&pex_msg[0], &pex_msg[0] + pex_msg.size(), m, ec);
int ret = bdecode(&pex_msg[0], &pex_msg[0] + pex_msg.size(), m, ec);
TORRENT_ASSERT(ret == 0);
TORRENT_ASSERT(!ec);
int num_dropped = 0;
int num_added = 0;
lazy_entry const* e = m.dict_find_string("added");
if (e) num_added += e->string_length() / 6;
bdecode_node e = m.dict_find_string("added");
if (e) num_added += e.string_length() / 6;
e = m.dict_find_string("dropped");
if (e) num_dropped += e->string_length() / 6;
if (e) num_dropped += e.string_length() / 6;
e = m.dict_find_string("added6");
if (e) num_added += e->string_length() / 18;
if (e) num_added += e.string_length() / 18;
e = m.dict_find_string("dropped6");
if (e) num_dropped += e->string_length() / 18;
if (e) num_dropped += e.string_length() / 18;
m_pc.peer_log("==> PEX_DIFF [ dropped: %d added: %d msg_size: %d ]"
, num_dropped, num_added, int(pex_msg.size()));
#endif

View File

@ -9,8 +9,12 @@ exe test_natpmp : test_natpmp.cpp /torrent//torrent
exe enum_if : enum_if.cpp /torrent//torrent
: <threading>multi <debug-iterators>on <invariant-checks>full ;
exe bdecode_benchmark : test_bdecode_performance.cpp /torrent//torrent
: <variant>release ;
explicit test_natpmp ;
explicit enum_if ;
explicit bdecode_benchmark ;
rule link_test ( properties * )
{
@ -117,6 +121,7 @@ test-suite libtorrent :
[ run test_buffer.cpp ]
[ run test_piece_picker.cpp ]
[ run test_bencoding.cpp ]
[ run test_bdecode.cpp ]
[ run test_fast_extension.cpp ]
[ run test_primitives.cpp ]
[ run test_http_parser.cpp ]
@ -149,7 +154,6 @@ test-suite libtorrent :
[ run test_web_seed_http_pw.cpp ]
[ run test_web_seed_chunked.cpp ]
[ run test_web_seed_ban.cpp ]
[ run test_bdecode_performance.cpp ]
[ run test_pe_crypto.cpp ]
[ run test_dos_blocker.cpp ]

View File

@ -602,7 +602,6 @@ void create_random_files(std::string const& path, const int file_sizes[], int nu
boost::shared_ptr<torrent_info> create_torrent(std::ostream* file, int piece_size
, int num_pieces, bool add_tracker, std::string ssl_certificate)
{
char const* tracker_url = "http://non-existent-name.com/announce";
// excercise the path when encountering invalid urls
char const* invalid_tracker_url = "http:";
char const* invalid_tracker_protocol = "foo://non/existent-name.com/announce";
@ -613,7 +612,6 @@ boost::shared_ptr<torrent_info> create_torrent(std::ostream* file, int piece_siz
libtorrent::create_torrent t(fs, piece_size);
if (add_tracker)
{
t.add_tracker(tracker_url);
t.add_tracker(invalid_tracker_url);
t.add_tracker(invalid_tracker_protocol);
}

1169
test/test_bdecode.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,9 @@ POSSIBILITY OF SUCH DAMAGE.
*/
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/bdecode.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/sha1_hash.hpp"
#include <boost/lexical_cast.hpp>
#include <iostream>
@ -39,22 +42,143 @@ POSSIBILITY OF SUCH DAMAGE.
using namespace libtorrent;
int test_main()
int load_file(std::string const& filename, std::vector<char>& v
, libtorrent::error_code& ec, int limit = 8000000)
{
using namespace libtorrent;
time_point start(clock_type::now());
for (int i = 0; i < 100000; ++i)
ec.clear();
FILE* f = fopen(filename.c_str(), "rb");
if (f == NULL)
{
char b[] = "d1:ai12453e1:b3:aaa1:c3:bbbe";
lazy_entry e;
error_code ec;
lazy_bdecode(b, b + sizeof(b)-1, e, ec);
ec.assign(errno, boost::system::generic_category());
return -1;
}
int r = fseek(f, 0, SEEK_END);
if (r != 0)
{
ec.assign(errno, boost::system::generic_category());
fclose(f);
return -1;
}
long s = ftell(f);
if (s < 0)
{
ec.assign(errno, boost::system::generic_category());
fclose(f);
return -1;
}
if (s > limit)
{
fclose(f);
return -2;
}
r = fseek(f, 0, SEEK_SET);
if (r != 0)
{
ec.assign(errno, boost::system::generic_category());
fclose(f);
return -1;
}
v.resize(s);
if (s == 0)
{
fclose(f);
return 0;
}
r = fread(&v[0], 1, v.size(), f);
if (r < 0)
{
ec.assign(errno, boost::system::generic_category());
fclose(f);
return -1;
}
fclose(f);
if (r != s) return -3;
return 0;
}
int main(int argc, char* argv[])
{
using namespace libtorrent;
if (argc != 2)
{
fputs("usage: bdecode_benchmark torrent-file\n", stderr);
return 1;
}
std::vector<char> buf;
error_code ec;
int ret = load_file(argv[1], buf, ec, 40 * 1000000);
if (ret == -1)
{
fprintf(stderr, "file too big, aborting\n");
return 1;
}
if (ret != 0)
{
fprintf(stderr, "failed to load file: %s\n", ec.message().c_str());
return 1;
}
{
time_point start(clock_type::now());
entry e;
for (int i = 0; i < 1000000; ++i)
{
int len;
e = bdecode(&buf[0], &buf[0] + buf.size(), len);
// entry& info = e["info"];
}
ptime stop(time_now_hires());
fprintf(stderr, "(slow) bdecode done in %5d ns per message\n"
, int(total_microseconds(stop - start) / 1000));
}
// ===============================================
{
ptime start(time_now_hires());
lazy_entry e;
for (int i = 0; i < 1000000; ++i)
{
error_code ec;
lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec);
// lazy_entry* info = e.dict_find("info");
}
time_point stop(clock_type::now());
fprintf(stderr, "lazy_bdecode done in %5d ns per message\n"
, int(total_microseconds(stop - start) / 1000));
}
// ===============================================
{
ptime start(time_now_hires());
bdecode_node e;
e.reserve(100);
for (int i = 0; i < 1000000; ++i)
{
error_code ec;
bdecode(&buf[0], &buf[0] + buf.size(), e, ec);
// bdecode_node info = e.dict_find("info");
}
ptime stop(time_now_hires());
fprintf(stderr, "bdecode done in %5d ns per message\n"
, int(total_microseconds(stop - start) / 1000));
}
time_point stop(clock_type::now());
std::cout << "done in " << total_milliseconds(stop - start) / 100. << " seconds per million message" << std::endl;
return 0;
}

View File

@ -31,11 +31,14 @@ POSSIBILITY OF SUCH DAMAGE.
*/
#include "libtorrent/bencode.hpp"
#include "libtorrent/lazy_entry.hpp"
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <cstring>
#ifndef TORRENT_NO_DEPRECATE
#include "libtorrent/lazy_entry.hpp"
#endif
#include "test.hpp"
using namespace libtorrent;
@ -57,8 +60,6 @@ entry decode(std::string const& str)
int test_main()
{
using namespace libtorrent;
// ** strings **
{
entry e("spam");
@ -104,6 +105,7 @@ int test_main()
TEST_CHECK(decode(encode(e)) == e);
}
#ifndef TORRENT_NO_DEPRECATE
{
char b[] = "i12453e";
lazy_entry e;
@ -347,7 +349,7 @@ int test_main()
int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, NULL);
TEST_CHECK(ret != 0);
printf("%s\n", print_entry(e).c_str());
TEST_EQUAL(ec, error_code(bdecode_errors::expected_string
TEST_EQUAL(ec, error_code(bdecode_errors::expected_digit
, get_bdecode_category()));
}
@ -386,7 +388,7 @@ int test_main()
int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, NULL);
TEST_CHECK(ret != 0);
printf("%s\n", print_entry(e).c_str());
TEST_EQUAL(ec, error_code(bdecode_errors::expected_string
TEST_EQUAL(ec, error_code(bdecode_errors::expected_digit
, get_bdecode_category()));
}
@ -564,7 +566,7 @@ int test_main()
boost::int64_t val = 0;
bdecode_errors::error_code_enum ec;
char const* e = parse_int(b, b + sizeof(b)-1, 'e', val, ec);
TEST_EQUAL(ec, bdecode_errors::expected_string);
TEST_EQUAL(ec, bdecode_errors::expected_digit);
TEST_EQUAL(e, b + 1);
}
@ -583,6 +585,7 @@ int test_main()
char const* e = parse_int(b, b + sizeof(b)-1, ':', val, ec);
TEST_CHECK(ec == bdecode_errors::expected_colon);
}
#endif // TORRENT_NO_DEPRECATE
return 0;
}

View File

@ -72,12 +72,16 @@ struct test_storage_impl : storage_interface
}
virtual bool has_any_file(storage_error& ec) { return false; }
virtual void set_file_priority(std::vector<boost::uint8_t> const& prio, storage_error& ec) {}
virtual int move_storage(std::string const& save_path, int flags, storage_error& ec) { return 0; }
virtual bool verify_resume_data(lazy_entry const& rd, storage_error& ec) { return true; }
virtual void set_file_priority(std::vector<boost::uint8_t> const& prio
, storage_error& ec) {}
virtual int move_storage(std::string const& save_path, int flags, storage_error& ec)
{ return 0; }
virtual bool verify_resume_data(bdecode_node const& rd, storage_error& ec)
{ return true; }
virtual void write_resume_data(entry& rd, storage_error& ec) const {}
virtual void release_files(storage_error& ec) {}
virtual void rename_file(int index, std::string const& new_filenamem, storage_error& ec) {}
virtual void rename_file(int index, std::string const& new_filenamem
, storage_error& ec) {}
virtual void delete_files(storage_error& ec) {}
virtual void finalize_file(int, storage_error&) {}
};

View File

@ -127,17 +127,17 @@ find_packet(udp::endpoint ep)
, boost::bind(&std::pair<udp::endpoint, entry>::first, _1) == ep);
}
void lazy_from_entry(entry const& e, lazy_entry& l)
void lazy_from_entry(entry const& e, bdecode_node& l)
{
error_code ec;
static char inbuf[1500];
int len = bencode(inbuf, e);
int ret = lazy_bdecode(inbuf, inbuf + len, l, ec);
int ret = bdecode(inbuf, inbuf + len, l, ec);
TEST_CHECK(ret == 0);
}
void send_dht_request(node_impl& node, char const* msg, udp::endpoint const& ep
, lazy_entry* reply, char const* t = "10", char const* info_hash = 0
, bdecode_node* reply, char const* t = "10", char const* info_hash = 0
, char const* name = 0, std::string const token = std::string(), int port = 0
, char const* target = 0, entry const* value = 0
, bool scrape = false, bool seed = false
@ -179,10 +179,10 @@ void send_dht_request(node_impl& node, char const* msg, udp::endpoint const& ep
VALGRIND_CHECK_MEM_IS_DEFINED(msg_buf, size);
#endif
lazy_entry decoded;
bdecode_node decoded;
error_code ec;
lazy_bdecode(msg_buf, msg_buf + size, decoded, ec);
if (ec) fprintf(stderr, "lazy_bdecode failed: %s\n", ec.message().c_str());
bdecode(msg_buf, msg_buf + size, decoded, ec);
if (ec) fprintf(stderr, "bdecode failed: %s\n", ec.message().c_str());
dht::msg m(decoded, ep);
node.incoming(m);
@ -222,7 +222,7 @@ void write_peers(entry::dictionary_type& r, std::set<tcp::endpoint> const& peers
}
}
void send_dht_response(node_impl& node, lazy_entry const& request, udp::endpoint const& ep
void send_dht_response(node_impl& node, bdecode_node const& request, udp::endpoint const& ep
, nodes_t const& nodes = nodes_t()
, std::string const token = std::string(), int port = 0
, std::set<tcp::endpoint> const& peers = std::set<tcp::endpoint>()
@ -256,10 +256,10 @@ void send_dht_response(node_impl& node, lazy_entry const& request, udp::endpoint
VALGRIND_CHECK_MEM_IS_DEFINED(msg_buf, size);
#endif
lazy_entry decoded;
bdecode_node decoded;
error_code ec;
lazy_bdecode(msg_buf, msg_buf + size, decoded, ec);
if (ec) fprintf(stderr, "lazy_bdecode failed: %s\n", ec.message().c_str());
bdecode(msg_buf, msg_buf + size, decoded, ec);
if (ec) fprintf(stderr, "bdecode failed: %s\n", ec.message().c_str());
dht::msg m(decoded, ep);
node.incoming(m);
@ -295,28 +295,29 @@ void announce_immutable_items(node_impl& node, udp::endpoint const* eps
for (int j = 0; j < num_items; ++j)
{
if ((i % items[j].num_peers) == 0) continue;
lazy_entry response;
bdecode_node response;
send_dht_request(node, "get", eps[i], &response, "10", 0
, 0, no, 0, (char const*)&items[j].target[0]);
key_desc_t desc[] =
{
{ "r", lazy_entry::dict_t, 0, key_desc_t::parse_children },
{ "id", lazy_entry::string_t, 20, 0},
{ "token", lazy_entry::string_t, 0, 0},
{ "ip", lazy_entry::string_t, 0, key_desc_t::optional | key_desc_t::last_child},
{ "y", lazy_entry::string_t, 1, 0},
{ "r", bdecode_node::dict_t, 0, key_desc_t::parse_children },
{ "id", bdecode_node::string_t, 20, 0},
{ "token", bdecode_node::string_t, 0, 0},
{ "ip", bdecode_node::string_t, 0, key_desc_t::optional | key_desc_t::last_child},
{ "y", bdecode_node::string_t, 1, 0},
};
lazy_entry const* parsed[6];
bdecode_node parsed[6];
char error_string[200];
// fprintf(stderr, "msg: %s\n", print_entry(response).c_str());
int ret = verify_message(&response, desc, parsed, 5, error_string, sizeof(error_string));
int ret = verify_message(response, desc, parsed, 5, error_string
, sizeof(error_string));
if (ret)
{
TEST_EQUAL(parsed[4]->string_value(), "r");
token = parsed[2]->string_value();
TEST_EQUAL(parsed[4].string_value(), "r");
token = parsed[2].string_value();
// fprintf(stderr, "got token: %s\n", token.c_str());
}
else
@ -329,7 +330,7 @@ void announce_immutable_items(node_impl& node, udp::endpoint const* eps
if (parsed[3])
{
address_v4::bytes_type b;
memcpy(&b[0], parsed[3]->string_ptr(), b.size());
memcpy(&b[0], parsed[3].string_ptr(), b.size());
address_v4 addr(b);
TEST_EQUAL(addr, eps[i].address());
}
@ -339,16 +340,17 @@ void announce_immutable_items(node_impl& node, udp::endpoint const* eps
key_desc_t desc2[] =
{
{ "y", lazy_entry::string_t, 1, 0 }
{ "y", bdecode_node::string_t, 1, 0 }
};
ret = verify_message(&response, desc2, parsed, 1, error_string, sizeof(error_string));
ret = verify_message(response, desc2, parsed, 1, error_string
, sizeof(error_string));
if (ret)
{
if (parsed[0]->string_value() != "r")
if (parsed[0].string_value() != "r")
fprintf(stderr, "msg: %s\n", print_entry(response).c_str());
TEST_EQUAL(parsed[0]->string_value(), "r");
TEST_EQUAL(parsed[0].string_value(), "r");
}
else
{
@ -362,22 +364,23 @@ void announce_immutable_items(node_impl& node, udp::endpoint const* eps
std::set<int> items_num;
for (int j = 0; j < num_items; ++j)
{
lazy_entry response;
bdecode_node response;
send_dht_request(node, "get", eps[j], &response, "10", 0
, 0, no, 0, (char const*)&items[j].target[0]);
key_desc_t desc[] =
{
{ "r", lazy_entry::dict_t, 0, key_desc_t::parse_children },
{ "v", lazy_entry::dict_t, 0, 0},
{ "id", lazy_entry::string_t, 20, key_desc_t::last_child},
{ "y", lazy_entry::string_t, 1, 0},
{ "r", bdecode_node::dict_t, 0, key_desc_t::parse_children },
{ "v", bdecode_node::dict_t, 0, 0},
{ "id", bdecode_node::string_t, 20, key_desc_t::last_child},
{ "y", bdecode_node::string_t, 1, 0},
};
lazy_entry const* parsed[4];
bdecode_node parsed[4];
char error_string[200];
int ret = verify_message(&response, desc, parsed, 4, error_string, sizeof(error_string));
int ret = verify_message(response, desc, parsed, 4, error_string
, sizeof(error_string));
if (ret)
{
items_num.insert(items_num.begin(), j);
@ -447,8 +450,8 @@ int test_main()
dht::node_impl node(&ad, &s, sett, node_id(0), ext, 0, cnt);
// DHT should be running on port 48199 now
lazy_entry response;
lazy_entry const* parsed[11];
bdecode_node response;
bdecode_node parsed[11];
char error_string[200];
bool ret;
@ -457,19 +460,20 @@ int test_main()
send_dht_request(node, "ping", source, &response, "10");
dht::key_desc_t pong_desc[] = {
{"y", lazy_entry::string_t, 1, 0},
{"t", lazy_entry::string_t, 2, 0},
{"r", lazy_entry::dict_t, 0, key_desc_t::parse_children},
{"id", lazy_entry::string_t, 20, key_desc_t::last_child},
{"y", bdecode_node::string_t, 1, 0},
{"t", bdecode_node::string_t, 2, 0},
{"r", bdecode_node::dict_t, 0, key_desc_t::parse_children},
{"id", bdecode_node::string_t, 20, key_desc_t::last_child},
};
fprintf(stderr, "msg: %s\n", print_entry(response).c_str());
ret = dht::verify_message(&response, pong_desc, parsed, 4, error_string, sizeof(error_string));
ret = dht::verify_message(response, pong_desc, parsed, 4, error_string
, sizeof(error_string));
TEST_CHECK(ret);
if (ret)
{
TEST_CHECK(parsed[0]->string_value() == "r");
TEST_CHECK(parsed[1]->string_value() == "10");
TEST_CHECK(parsed[0].string_value() == "r");
TEST_CHECK(parsed[1].string_value() == "10");
}
else
{
@ -481,20 +485,21 @@ int test_main()
send_dht_request(node, "find_node", source, &response, "10");
dht::key_desc_t err_desc[] = {
{"y", lazy_entry::string_t, 1, 0},
{"e", lazy_entry::list_t, 2, 0}
{"y", bdecode_node::string_t, 1, 0},
{"e", bdecode_node::list_t, 2, 0}
};
fprintf(stderr, "msg: %s\n", print_entry(response).c_str());
ret = dht::verify_message(&response, err_desc, parsed, 2, error_string, sizeof(error_string));
ret = dht::verify_message(response, err_desc, parsed, 2, error_string
, sizeof(error_string));
TEST_CHECK(ret);
if (ret)
{
TEST_CHECK(parsed[0]->string_value() == "e");
if (parsed[1]->list_at(0)->type() == lazy_entry::int_t
&& parsed[1]->list_at(1)->type() == lazy_entry::string_t)
TEST_CHECK(parsed[0].string_value() == "e");
if (parsed[1].list_at(0).type() == bdecode_node::int_t
&& parsed[1].list_at(1).type() == bdecode_node::string_t)
{
TEST_CHECK(parsed[1]->list_at(1)->string_value() == "missing 'target' key");
TEST_CHECK(parsed[1].list_at(1).string_value() == "missing 'target' key");
}
else
{
@ -511,20 +516,21 @@ int test_main()
send_dht_request(node, "get_peers", source, &response, "10", "01010101010101010101");
dht::key_desc_t peer1_desc[] = {
{"y", lazy_entry::string_t, 1, 0},
{"r", lazy_entry::dict_t, 0, key_desc_t::parse_children},
{"token", lazy_entry::string_t, 0, 0},
{"id", lazy_entry::string_t, 20, key_desc_t::last_child},
{"y", bdecode_node::string_t, 1, 0},
{"r", bdecode_node::dict_t, 0, key_desc_t::parse_children},
{"token", bdecode_node::string_t, 0, 0},
{"id", bdecode_node::string_t, 20, key_desc_t::last_child},
};
std::string token;
fprintf(stderr, "msg: %s\n", print_entry(response).c_str());
ret = dht::verify_message(&response, peer1_desc, parsed, 4, error_string, sizeof(error_string));
ret = dht::verify_message(response, peer1_desc, parsed, 4, error_string
, sizeof(error_string));
TEST_CHECK(ret);
if (ret)
{
TEST_CHECK(parsed[0]->string_value() == "r");
token = parsed[2]->string_value();
TEST_CHECK(parsed[0].string_value() == "r");
token = parsed[2].string_value();
// fprintf(stderr, "got token: %s\n", token.c_str());
}
else
@ -538,17 +544,18 @@ int test_main()
send_dht_request(node, "announce_peer", source, &response, "10", "01010101010101010101", "test", token, 8080);
dht::key_desc_t ann_desc[] = {
{"y", lazy_entry::string_t, 1, 0},
{"r", lazy_entry::dict_t, 0, key_desc_t::parse_children},
{"id", lazy_entry::string_t, 20, key_desc_t::last_child},
{"y", bdecode_node::string_t, 1, 0},
{"r", bdecode_node::dict_t, 0, key_desc_t::parse_children},
{"id", bdecode_node::string_t, 20, key_desc_t::last_child},
};
fprintf(stderr, "msg: %s\n", print_entry(response).c_str());
ret = dht::verify_message(&response, ann_desc, parsed, 3, error_string, sizeof(error_string));
ret = dht::verify_message(response, ann_desc, parsed, 3, error_string
, sizeof(error_string));
TEST_CHECK(ret);
if (ret)
{
TEST_CHECK(parsed[0]->string_value() == "r");
TEST_CHECK(parsed[0].string_value() == "r");
}
else
{
@ -561,12 +568,13 @@ int test_main()
{
source = udp::endpoint(rand_v4(), 6000);
send_dht_request(node, "get_peers", source, &response, "10", "01010101010101010101");
ret = dht::verify_message(&response, peer1_desc, parsed, 4, error_string, sizeof(error_string));
ret = dht::verify_message(response, peer1_desc, parsed, 4, error_string
, sizeof(error_string));
if (ret)
{
TEST_CHECK(parsed[0]->string_value() == "r");
token = parsed[2]->string_value();
TEST_CHECK(parsed[0].string_value() == "r");
token = parsed[2].string_value();
// fprintf(stderr, "got token: %s\n", token.c_str());
}
else
@ -586,25 +594,26 @@ int test_main()
, 0, no, 0, 0, 0, true);
dht::key_desc_t peer2_desc[] = {
{"y", lazy_entry::string_t, 1, 0},
{"r", lazy_entry::dict_t, 0, key_desc_t::parse_children},
{"BFpe", lazy_entry::string_t, 256, 0},
{"BFsd", lazy_entry::string_t, 256, 0},
{"id", lazy_entry::string_t, 20, key_desc_t::last_child},
{"y", bdecode_node::string_t, 1, 0},
{"r", bdecode_node::dict_t, 0, key_desc_t::parse_children},
{"BFpe", bdecode_node::string_t, 256, 0},
{"BFsd", bdecode_node::string_t, 256, 0},
{"id", bdecode_node::string_t, 20, key_desc_t::last_child},
};
fprintf(stderr, "msg: %s\n", print_entry(response).c_str());
ret = dht::verify_message(&response, peer2_desc, parsed, 5, error_string, sizeof(error_string));
ret = dht::verify_message(response, peer2_desc, parsed, 5, error_string
, sizeof(error_string));
TEST_CHECK(ret);
if (ret)
{
TEST_CHECK(parsed[0]->string_value() == "r");
TEST_EQUAL(parsed[1]->dict_find_string_value("n"), "test");
TEST_CHECK(parsed[0].string_value() == "r");
TEST_EQUAL(parsed[1].dict_find_string_value("n"), "test");
bloom_filter<256> downloaders;
bloom_filter<256> seeds;
downloaders.from_string(parsed[2]->string_ptr());
seeds.from_string(parsed[3]->string_ptr());
downloaders.from_string(parsed[2].string_ptr());
seeds.from_string(parsed[3].string_ptr());
fprintf(stderr, "seeds: %f\n", seeds.size());
fprintf(stderr, "downloaders: %f\n", downloaders.size());
@ -644,17 +653,18 @@ int test_main()
, 0, "0101010101010101010101010101010101010101", 0, false, false, std::string(), std::string(), -1, 0, &nid);
dht::key_desc_t nodes_desc[] = {
{"y", lazy_entry::string_t, 1, 0},
{"r", lazy_entry::dict_t, 0, key_desc_t::parse_children},
{"id", lazy_entry::string_t, 20, key_desc_t::last_child},
{"y", bdecode_node::string_t, 1, 0},
{"r", bdecode_node::dict_t, 0, key_desc_t::parse_children},
{"id", bdecode_node::string_t, 20, key_desc_t::last_child},
};
fprintf(stderr, "msg: %s\n", print_entry(response).c_str());
ret = dht::verify_message(&response, nodes_desc, parsed, 3, error_string, sizeof(error_string));
ret = dht::verify_message(response, nodes_desc, parsed, 3, error_string
, sizeof(error_string));
TEST_CHECK(ret);
if (ret)
{
TEST_CHECK(parsed[0]->string_value() == "r");
TEST_CHECK(parsed[0].string_value() == "r");
}
else
{
@ -668,15 +678,16 @@ int test_main()
send_dht_request(node, "find_node", source, &response, "10", 0, 0, std::string()
, 0, "0101010101010101010101010101010101010101", 0, false, false, std::string(), std::string(), -1, 0, &nid);
ret = dht::verify_message(&response, err_desc, parsed, 2, error_string, sizeof(error_string));
ret = dht::verify_message(response, err_desc, parsed, 2, error_string
, sizeof(error_string));
TEST_CHECK(ret);
if (ret)
{
TEST_CHECK(parsed[0]->string_value() == "e");
if (parsed[1]->list_at(0)->type() == lazy_entry::int_t
&& parsed[1]->list_at(1)->type() == lazy_entry::string_t)
TEST_CHECK(parsed[0].string_value() == "e");
if (parsed[1].list_at(0).type() == bdecode_node::int_t
&& parsed[1].list_at(1).type() == bdecode_node::string_t)
{
TEST_CHECK(parsed[1]->list_at(1)->string_value() == "invalid node ID");
TEST_CHECK(parsed[1].list_at(1).string_value() == "invalid node ID");
}
else
{
@ -761,13 +772,13 @@ int test_main()
key_desc_t desc2[] =
{
{ "y", lazy_entry::string_t, 1, 0 }
{ "y", bdecode_node::string_t, 1, 0 }
};
key_desc_t desc_error[] =
{
{ "e", lazy_entry::list_t, 2, 0 },
{ "y", lazy_entry::string_t, 1, 0},
{ "e", bdecode_node::list_t, 2, 0 },
{ "y", bdecode_node::string_t, 1, 0},
};
// ==== get / put mutable items ===
@ -814,18 +825,19 @@ int test_main()
key_desc_t desc[] =
{
{ "r", lazy_entry::dict_t, 0, key_desc_t::parse_children },
{ "id", lazy_entry::string_t, 20, 0},
{ "token", lazy_entry::string_t, 0, 0},
{ "ip", lazy_entry::string_t, 0, key_desc_t::optional | key_desc_t::last_child},
{ "y", lazy_entry::string_t, 1, 0},
{ "r", bdecode_node::dict_t, 0, key_desc_t::parse_children },
{ "id", bdecode_node::string_t, 20, 0},
{ "token", bdecode_node::string_t, 0, 0},
{ "ip", bdecode_node::string_t, 0, key_desc_t::optional | key_desc_t::last_child},
{ "y", bdecode_node::string_t, 1, 0},
};
ret = verify_message(&response, desc, parsed, 5, error_string, sizeof(error_string));
ret = verify_message(response, desc, parsed, 5, error_string
, sizeof(error_string));
if (ret)
{
TEST_EQUAL(parsed[4]->string_value(), "r");
token = parsed[2]->string_value();
TEST_EQUAL(parsed[4].string_value(), "r");
token = parsed[2].string_value();
fprintf(stderr, "get response: %s\n"
, print_entry(response).c_str());
fprintf(stderr, "got token: %s\n", to_hex(token).c_str());
@ -850,12 +862,13 @@ int test_main()
, std::string(public_key, item_pk_len)
, std::string(signature, item_sig_len), seq, -1, NULL, salt.first);
ret = verify_message(&response, desc2, parsed, 1, error_string, sizeof(error_string));
ret = verify_message(response, desc2, parsed, 1, error_string
, sizeof(error_string));
if (ret)
{
fprintf(stderr, "put response: %s\n"
, print_entry(response).c_str());
TEST_EQUAL(parsed[0]->string_value(), "r");
TEST_EQUAL(parsed[0].string_value(), "r");
}
else
{
@ -873,16 +886,17 @@ int test_main()
key_desc_t desc3[] =
{
{ "r", lazy_entry::dict_t, 0, key_desc_t::parse_children },
{ "id", lazy_entry::string_t, 20, 0},
{ "v", lazy_entry::none_t, 0, 0},
{ "seq", lazy_entry::int_t, 0, 0},
{ "sig", lazy_entry::string_t, 0, 0},
{ "ip", lazy_entry::string_t, 0, key_desc_t::optional | key_desc_t::last_child},
{ "y", lazy_entry::string_t, 1, 0},
{ "r", bdecode_node::dict_t, 0, key_desc_t::parse_children },
{ "id", bdecode_node::string_t, 20, 0},
{ "v", bdecode_node::none_t, 0, 0},
{ "seq", bdecode_node::int_t, 0, 0},
{ "sig", bdecode_node::string_t, 0, 0},
{ "ip", bdecode_node::string_t, 0, key_desc_t::optional | key_desc_t::last_child},
{ "y", bdecode_node::string_t, 1, 0},
};
ret = verify_message(&response, desc3, parsed, 7, error_string, sizeof(error_string));
ret = verify_message(response, desc3, parsed, 7, error_string
, sizeof(error_string));
if (ret == 0)
{
fprintf(stderr, "msg: %s\n", print_entry(response).c_str());
@ -897,10 +911,10 @@ int test_main()
char value[1020];
char* ptr = value;
int value_len = bencode(ptr, items[0].ent);
TEST_EQUAL(value_len, parsed[2]->data_section().second);
TEST_CHECK(memcmp(parsed[2]->data_section().first, value, value_len) == 0);
TEST_EQUAL(value_len, parsed[2].data_section().second);
TEST_CHECK(memcmp(parsed[2].data_section().first, value, value_len) == 0);
TEST_EQUAL(seq, parsed[3]->int_value());
TEST_EQUAL(seq, parsed[3].int_value());
}
// also test that invalid signatures fail!
@ -923,13 +937,14 @@ int test_main()
, std::string(public_key, item_pk_len)
, std::string(signature, item_sig_len), seq, -1, NULL, salt.first);
ret = verify_message(&response, desc_error, parsed, 2, error_string, sizeof(error_string));
ret = verify_message(response, desc_error, parsed, 2, error_string
, sizeof(error_string));
if (ret)
{
fprintf(stderr, "put response: %s\n", print_entry(response).c_str());
TEST_EQUAL(parsed[1]->string_value(), "e");
TEST_EQUAL(parsed[1].string_value(), "e");
// 206 is the code for invalid signature
TEST_EQUAL(parsed[0]->list_int_value_at(0), 206);
TEST_EQUAL(parsed[0].list_int_value_at(0), 206);
}
else
{
@ -945,10 +960,10 @@ int test_main()
, 0, false, false, std::string(), std::string(), seq-1);
{
lazy_entry const* r = response.dict_find_dict("r");
TEST_CHECK(r->dict_find("v"));
TEST_CHECK(r->dict_find("k"));
TEST_CHECK(r->dict_find("sig"));
bdecode_node r = response.dict_find_dict("r");
TEST_CHECK(r.dict_find("v"));
TEST_CHECK(r.dict_find("k"));
TEST_CHECK(r.dict_find("sig"));
}
send_dht_request(node, "get", source, &response, "10", 0
@ -956,10 +971,10 @@ int test_main()
, 0, false, false, std::string(), std::string(), seq);
{
lazy_entry const* r = response.dict_find_dict("r");
TEST_CHECK(!r->dict_find("v"));
TEST_CHECK(!r->dict_find("k"));
TEST_CHECK(!r->dict_find("sig"));
bdecode_node r = response.dict_find_dict("r");
TEST_CHECK(!r.dict_find("v"));
TEST_CHECK(!r.dict_find("k"));
TEST_CHECK(!r.dict_find("sig"));
}
// === test CAS put ===
@ -987,12 +1002,13 @@ int test_main()
, std::string(signature, item_sig_len), seq
, cas, NULL, salt.first);
ret = verify_message(&response, desc2, parsed, 1, error_string, sizeof(error_string));
ret = verify_message(response, desc2, parsed, 1, error_string
, sizeof(error_string));
if (ret)
{
fprintf(stderr, "put response: %s\n"
, print_entry(response).c_str());
TEST_EQUAL(parsed[0]->string_value(), "r");
TEST_EQUAL(parsed[0].string_value(), "r");
}
else
{
@ -1012,14 +1028,15 @@ int test_main()
, std::string(signature, item_sig_len), seq
, cas, NULL, salt.first);
ret = verify_message(&response, desc_error, parsed, 2, error_string, sizeof(error_string));
ret = verify_message(response, desc_error, parsed, 2, error_string
, sizeof(error_string));
if (ret)
{
fprintf(stderr, "put response: %s\n"
, print_entry(response).c_str());
TEST_EQUAL(parsed[1]->string_value(), "e");
TEST_EQUAL(parsed[1].string_value(), "e");
// 301 is the error code for CAS hash mismatch
TEST_EQUAL(parsed[0]->list_int_value_at(0), 301);
TEST_EQUAL(parsed[0].list_int_value_at(0), 301);
}
else
{
@ -1077,94 +1094,99 @@ int test_main()
// test verify_message
const static key_desc_t msg_desc[] = {
{"A", lazy_entry::string_t, 4, 0},
{"B", lazy_entry::dict_t, 0, key_desc_t::optional | key_desc_t::parse_children},
{"B1", lazy_entry::string_t, 0, 0},
{"B2", lazy_entry::string_t, 0, key_desc_t::last_child},
{"C", lazy_entry::dict_t, 0, key_desc_t::optional | key_desc_t::parse_children},
{"C1", lazy_entry::string_t, 0, 0},
{"C2", lazy_entry::string_t, 0, key_desc_t::last_child},
{"A", bdecode_node::string_t, 4, 0},
{"B", bdecode_node::dict_t, 0, key_desc_t::optional | key_desc_t::parse_children},
{"B1", bdecode_node::string_t, 0, 0},
{"B2", bdecode_node::string_t, 0, key_desc_t::last_child},
{"C", bdecode_node::dict_t, 0, key_desc_t::optional | key_desc_t::parse_children},
{"C1", bdecode_node::string_t, 0, 0},
{"C2", bdecode_node::string_t, 0, key_desc_t::last_child},
};
lazy_entry const* msg_keys[7];
bdecode_node msg_keys[7];
lazy_entry ent;
bdecode_node ent;
error_code ec;
char const test_msg[] = "d1:A4:test1:Bd2:B15:test22:B25:test3ee";
lazy_bdecode(test_msg, test_msg + sizeof(test_msg)-1, ent, ec);
bdecode(test_msg, test_msg + sizeof(test_msg)-1, ent, ec);
fprintf(stderr, "%s\n", print_entry(ent).c_str());
ret = verify_message(&ent, msg_desc, msg_keys, 7, error_string, sizeof(error_string));
ret = verify_message(ent, msg_desc, msg_keys, 7, error_string
, sizeof(error_string));
TEST_CHECK(ret);
TEST_CHECK(msg_keys[0]);
if (msg_keys[0]) TEST_EQUAL(msg_keys[0]->string_value(), "test");
if (msg_keys[0]) TEST_EQUAL(msg_keys[0].string_value(), "test");
TEST_CHECK(msg_keys[1]);
TEST_CHECK(msg_keys[2]);
if (msg_keys[2]) TEST_EQUAL(msg_keys[2]->string_value(), "test2");
if (msg_keys[2]) TEST_EQUAL(msg_keys[2].string_value(), "test2");
TEST_CHECK(msg_keys[3]);
if (msg_keys[3]) TEST_EQUAL(msg_keys[3]->string_value(), "test3");
TEST_CHECK(msg_keys[4] == 0);
TEST_CHECK(msg_keys[5] == 0);
TEST_CHECK(msg_keys[6] == 0);
if (msg_keys[3]) TEST_EQUAL(msg_keys[3].string_value(), "test3");
TEST_CHECK(!msg_keys[4]);
TEST_CHECK(!msg_keys[5]);
TEST_CHECK(!msg_keys[6]);
char const test_msg2[] = "d1:A4:test1:Cd2:C15:test22:C25:test3ee";
lazy_bdecode(test_msg2, test_msg2 + sizeof(test_msg2)-1, ent, ec);
bdecode(test_msg2, test_msg2 + sizeof(test_msg2)-1, ent, ec);
fprintf(stderr, "%s\n", print_entry(ent).c_str());
ret = verify_message(&ent, msg_desc, msg_keys, 7, error_string, sizeof(error_string));
ret = verify_message(ent, msg_desc, msg_keys, 7, error_string
, sizeof(error_string));
TEST_CHECK(ret);
TEST_CHECK(msg_keys[0]);
if (msg_keys[0]) TEST_EQUAL(msg_keys[0]->string_value(), "test");
TEST_CHECK(msg_keys[1] == 0);
TEST_CHECK(msg_keys[2] == 0);
TEST_CHECK(msg_keys[3] == 0);
if (msg_keys[0]) TEST_EQUAL(msg_keys[0].string_value(), "test");
TEST_CHECK(!msg_keys[1]);
TEST_CHECK(!msg_keys[2]);
TEST_CHECK(!msg_keys[3]);
TEST_CHECK(msg_keys[4]);
TEST_CHECK(msg_keys[5]);
if (msg_keys[5]) TEST_EQUAL(msg_keys[5]->string_value(), "test2");
if (msg_keys[5]) TEST_EQUAL(msg_keys[5].string_value(), "test2");
TEST_CHECK(msg_keys[6]);
if (msg_keys[6]) TEST_EQUAL(msg_keys[6]->string_value(), "test3");
if (msg_keys[6]) TEST_EQUAL(msg_keys[6].string_value(), "test3");
char const test_msg3[] = "d1:Cd2:C15:test22:C25:test3ee";
lazy_bdecode(test_msg3, test_msg3 + sizeof(test_msg3)-1, ent, ec);
bdecode(test_msg3, test_msg3 + sizeof(test_msg3)-1, ent, ec);
fprintf(stderr, "%s\n", print_entry(ent).c_str());
ret = verify_message(&ent, msg_desc, msg_keys, 7, error_string, sizeof(error_string));
ret = verify_message(ent, msg_desc, msg_keys, 7, error_string
, sizeof(error_string));
TEST_CHECK(!ret);
fprintf(stderr, "%s\n", error_string);
TEST_EQUAL(error_string, std::string("missing 'A' key"));
char const test_msg4[] = "d1:A6:foobare";
lazy_bdecode(test_msg4, test_msg4 + sizeof(test_msg4)-1, ent, ec);
bdecode(test_msg4, test_msg4 + sizeof(test_msg4)-1, ent, ec);
fprintf(stderr, "%s\n", print_entry(ent).c_str());
ret = verify_message(&ent, msg_desc, msg_keys, 7, error_string, sizeof(error_string));
ret = verify_message(ent, msg_desc, msg_keys, 7, error_string
, sizeof(error_string));
TEST_CHECK(!ret);
fprintf(stderr, "%s\n", error_string);
TEST_EQUAL(error_string, std::string("invalid value for 'A'"));
char const test_msg5[] = "d1:A4:test1:Cd2:C15:test2ee";
lazy_bdecode(test_msg5, test_msg5 + sizeof(test_msg5)-1, ent, ec);
bdecode(test_msg5, test_msg5 + sizeof(test_msg5)-1, ent, ec);
fprintf(stderr, "%s\n", print_entry(ent).c_str());
ret = verify_message(&ent, msg_desc, msg_keys, 7, error_string, sizeof(error_string));
ret = verify_message(ent, msg_desc, msg_keys, 7, error_string
, sizeof(error_string));
TEST_CHECK(!ret);
fprintf(stderr, "%s\n", error_string);
TEST_EQUAL(error_string, std::string("missing 'C2' key"));
// test empty strings [ { "":1 }, "" ]
char const test_msg6[] = "ld0:i1ee0:e";
lazy_bdecode(test_msg6, test_msg6 + sizeof(test_msg6)-1, ent, ec);
bdecode(test_msg6, test_msg6 + sizeof(test_msg6)-1, ent, ec);
fprintf(stderr, "%s\n", print_entry(ent).c_str());
TEST_CHECK(ent.type() == lazy_entry::list_t);
if (ent.type() == lazy_entry::list_t)
TEST_CHECK(ent.type() == bdecode_node::list_t);
if (ent.type() == bdecode_node::list_t)
{
TEST_CHECK(ent.list_size() == 2);
if (ent.list_size() == 2)
{
TEST_CHECK(ent.list_at(0)->dict_find_int_value("") == 1);
TEST_CHECK(ent.list_at(1)->string_value() == "");
TEST_CHECK(ent.list_at(0).dict_find_int_value("") == 1);
TEST_CHECK(ent.list_at(1).string_value() == "");
}
}
@ -1410,31 +1432,31 @@ int test_main()
// test traversal algorithms
dht::key_desc_t find_node_desc[] = {
{"y", lazy_entry::string_t, 1, 0},
{"t", lazy_entry::string_t, 2, 0},
{"q", lazy_entry::string_t, 9, 0},
{"a", lazy_entry::dict_t, 0, key_desc_t::parse_children},
{"id", lazy_entry::string_t, 20, 0},
{"target", lazy_entry::string_t, 20, key_desc_t::optional},
{"info_hash", lazy_entry::string_t, 20, key_desc_t::optional | key_desc_t::last_child},
{"y", bdecode_node::string_t, 1, 0},
{"t", bdecode_node::string_t, 2, 0},
{"q", bdecode_node::string_t, 9, 0},
{"a", bdecode_node::dict_t, 0, key_desc_t::parse_children},
{"id", bdecode_node::string_t, 20, 0},
{"target", bdecode_node::string_t, 20, key_desc_t::optional},
{"info_hash", bdecode_node::string_t, 20, key_desc_t::optional | key_desc_t::last_child},
};
dht::key_desc_t get_peers_desc[] = {
{"y", lazy_entry::string_t, 1, 0},
{"t", lazy_entry::string_t, 2, 0},
{"q", lazy_entry::string_t, 9, 0},
{"a", lazy_entry::dict_t, 0, key_desc_t::parse_children},
{"id", lazy_entry::string_t, 20, 0},
{"info_hash", lazy_entry::string_t, 20, key_desc_t::last_child},
{"y", bdecode_node::string_t, 1, 0},
{"t", bdecode_node::string_t, 2, 0},
{"q", bdecode_node::string_t, 9, 0},
{"a", bdecode_node::dict_t, 0, key_desc_t::parse_children},
{"id", bdecode_node::string_t, 20, 0},
{"info_hash", bdecode_node::string_t, 20, key_desc_t::last_child},
};
dht::key_desc_t get_item_desc[] = {
{"y", lazy_entry::string_t, 1, 0},
{"t", lazy_entry::string_t, 2, 0},
{"q", lazy_entry::string_t, 3, 0},
{"a", lazy_entry::dict_t, 0, key_desc_t::parse_children},
{"id", lazy_entry::string_t, 20, 0},
{"target", lazy_entry::string_t, 20, key_desc_t::last_child},
{"y", bdecode_node::string_t, 1, 0},
{"t", bdecode_node::string_t, 2, 0},
{"q", bdecode_node::string_t, 3, 0},
{"a", bdecode_node::dict_t, 0, key_desc_t::parse_children},
{"id", bdecode_node::string_t, 20, 0},
{"target", bdecode_node::string_t, 20, key_desc_t::last_child},
};
// bootstrap
@ -1454,16 +1476,17 @@ int test_main()
TEST_EQUAL(g_sent_packets.front().first, initial_node);
lazy_from_entry(g_sent_packets.front().second, response);
ret = verify_message(&response, find_node_desc, parsed, 7, error_string, sizeof(error_string));
ret = verify_message(response, find_node_desc, parsed, 7, error_string
, sizeof(error_string));
if (ret)
{
TEST_EQUAL(parsed[0]->string_value(), "q");
TEST_CHECK(parsed[2]->string_value() == "find_node"
|| parsed[2]->string_value() == "get_peers");
TEST_EQUAL(parsed[0].string_value(), "q");
TEST_CHECK(parsed[2].string_value() == "find_node"
|| parsed[2].string_value() == "get_peers");
if (parsed[0]->string_value() != "q"
|| (parsed[2]->string_value() != "find_node"
&& parsed[2]->string_value() != "get_peers")) break;
if (parsed[0].string_value() != "q"
|| (parsed[2].string_value() != "find_node"
&& parsed[2].string_value() != "get_peers")) break;
}
else
{
@ -1483,14 +1506,15 @@ int test_main()
TEST_EQUAL(g_sent_packets.front().first, found_node);
lazy_from_entry(g_sent_packets.front().second, response);
ret = verify_message(&response, find_node_desc, parsed, 7, error_string, sizeof(error_string));
ret = verify_message(response, find_node_desc, parsed, 7, error_string
, sizeof(error_string));
if (ret)
{
TEST_EQUAL(parsed[0]->string_value(), "q");
TEST_CHECK(parsed[2]->string_value() == "find_node"
|| parsed[2]->string_value() == "get_peers");
if (parsed[0]->string_value() != "q" || (parsed[2]->string_value() != "find_node"
&& parsed[2]->string_value() == "get_peers")) break;
TEST_EQUAL(parsed[0].string_value(), "q");
TEST_CHECK(parsed[2].string_value() == "find_node"
|| parsed[2].string_value() == "get_peers");
if (parsed[0].string_value() != "q" || (parsed[2].string_value() != "find_node"
&& parsed[2].string_value() == "get_peers")) break;
}
else
{
@ -1524,13 +1548,14 @@ int test_main()
TEST_EQUAL(g_sent_packets.front().first, initial_node);
lazy_from_entry(g_sent_packets.front().second, response);
ret = verify_message(&response, get_peers_desc, parsed, 6, error_string, sizeof(error_string));
ret = verify_message(response, get_peers_desc, parsed, 6, error_string
, sizeof(error_string));
if (ret)
{
TEST_EQUAL(parsed[0]->string_value(), "q");
TEST_EQUAL(parsed[2]->string_value(), "get_peers");
TEST_EQUAL(parsed[5]->string_value(), target.to_string());
if (parsed[0]->string_value() != "q" || parsed[2]->string_value() != "get_peers") break;
TEST_EQUAL(parsed[0].string_value(), "q");
TEST_EQUAL(parsed[2].string_value(), "get_peers");
TEST_EQUAL(parsed[5].string_value(), target.to_string());
if (parsed[0].string_value() != "q" || parsed[2].string_value() != "get_peers") break;
}
else
{
@ -1556,13 +1581,14 @@ int test_main()
TEST_EQUAL(g_sent_packets.front().first, next_node);
lazy_from_entry(g_sent_packets.front().second, response);
ret = verify_message(&response, get_peers_desc, parsed, 6, error_string, sizeof(error_string));
ret = verify_message(response, get_peers_desc, parsed, 6, error_string
, sizeof(error_string));
if (ret)
{
TEST_EQUAL(parsed[0]->string_value(), "q");
TEST_EQUAL(parsed[2]->string_value(), "get_peers");
TEST_EQUAL(parsed[5]->string_value(), target.to_string());
if (parsed[0]->string_value() != "q" || parsed[2]->string_value() != "get_peers") break;
TEST_EQUAL(parsed[0].string_value(), "q");
TEST_EQUAL(parsed[2].string_value(), "get_peers");
TEST_EQUAL(parsed[5].string_value(), target.to_string());
if (parsed[0].string_value() != "q" || parsed[2].string_value() != "get_peers") break;
}
else
{
@ -1615,13 +1641,14 @@ int test_main()
TEST_EQUAL(g_sent_packets.front().first, initial_node);
lazy_from_entry(g_sent_packets.front().second, response);
ret = verify_message(&response, get_item_desc, parsed, 6, error_string, sizeof(error_string));
ret = verify_message(response, get_item_desc, parsed, 6, error_string
, sizeof(error_string));
if (ret)
{
TEST_EQUAL(parsed[0]->string_value(), "q");
TEST_EQUAL(parsed[2]->string_value(), "get");
TEST_EQUAL(parsed[5]->string_value(), items[0].target.to_string());
if (parsed[0]->string_value() != "q" || parsed[2]->string_value() != "get") break;
TEST_EQUAL(parsed[0].string_value(), "q");
TEST_EQUAL(parsed[2].string_value(), "get");
TEST_EQUAL(parsed[5].string_value(), items[0].target.to_string());
if (parsed[0].string_value() != "q" || parsed[2].string_value() != "get") break;
}
else
{
@ -1661,13 +1688,14 @@ int test_main()
TEST_EQUAL(g_sent_packets.front().first, initial_node);
lazy_from_entry(g_sent_packets.front().second, response);
ret = verify_message(&response, get_item_desc, parsed, 6, error_string, sizeof(error_string));
ret = verify_message(response, get_item_desc, parsed, 6, error_string
, sizeof(error_string));
if (ret)
{
TEST_EQUAL(parsed[0]->string_value(), "q");
TEST_EQUAL(parsed[2]->string_value(), "get");
TEST_EQUAL(parsed[5]->string_value(), target.to_string());
if (parsed[0]->string_value() != "q" || parsed[2]->string_value() != "get") break;
TEST_EQUAL(parsed[0].string_value(), "q");
TEST_EQUAL(parsed[2].string_value(), "get");
TEST_EQUAL(parsed[5].string_value(), target.to_string());
if (parsed[0].string_value() != "q" || parsed[2].string_value() != "get") break;
}
else
{
@ -1696,27 +1724,27 @@ int test_main()
} while (false);
dht::key_desc_t put_immutable_item_desc[] = {
{"y", lazy_entry::string_t, 1, 0},
{"t", lazy_entry::string_t, 2, 0},
{"q", lazy_entry::string_t, 3, 0},
{"a", lazy_entry::dict_t, 0, key_desc_t::parse_children},
{"id", lazy_entry::string_t, 20, 0},
{"token", lazy_entry::string_t, 2, 0},
{"v", lazy_entry::none_t, 0, key_desc_t::last_child},
{"y", bdecode_node::string_t, 1, 0},
{"t", bdecode_node::string_t, 2, 0},
{"q", bdecode_node::string_t, 3, 0},
{"a", bdecode_node::dict_t, 0, key_desc_t::parse_children},
{"id", bdecode_node::string_t, 20, 0},
{"token", bdecode_node::string_t, 2, 0},
{"v", bdecode_node::none_t, 0, key_desc_t::last_child},
};
dht::key_desc_t put_mutable_item_desc[] = {
{"y", lazy_entry::string_t, 1, 0},
{"t", lazy_entry::string_t, 2, 0},
{"q", lazy_entry::string_t, 3, 0},
{"a", lazy_entry::dict_t, 0, key_desc_t::parse_children},
{"id", lazy_entry::string_t, 20, 0},
{"cas", lazy_entry::string_t, 20, key_desc_t::optional},
{"k", lazy_entry::string_t, item_pk_len, 0},
{"seq", lazy_entry::int_t, 0, 0},
{"sig", lazy_entry::string_t, item_sig_len, 0},
{"token", lazy_entry::string_t, 2, 0},
{"v", lazy_entry::none_t, 0, key_desc_t::last_child},
{"y", bdecode_node::string_t, 1, 0},
{"t", bdecode_node::string_t, 2, 0},
{"q", bdecode_node::string_t, 3, 0},
{"a", bdecode_node::dict_t, 0, key_desc_t::parse_children},
{"id", bdecode_node::string_t, 20, 0},
{"cas", bdecode_node::string_t, 20, key_desc_t::optional},
{"k", bdecode_node::string_t, item_pk_len, 0},
{"seq", bdecode_node::int_t, 0, 0},
{"sig", bdecode_node::string_t, item_sig_len, 0},
{"token", bdecode_node::string_t, 2, 0},
{"v", bdecode_node::none_t, 0, key_desc_t::last_child},
};
// immutable put
@ -1745,7 +1773,8 @@ int test_main()
if (packet == g_sent_packets.end()) continue;
lazy_from_entry(packet->second, response);
ret = verify_message(&response, get_item_desc, parsed, 6, error_string, sizeof(error_string));
ret = verify_message(response, get_item_desc, parsed, 6, error_string
, sizeof(error_string));
if (!ret)
{
fprintf(stderr, " invalid get request: %s\n", print_entry(response).c_str());
@ -1772,18 +1801,19 @@ int test_main()
if (packet == g_sent_packets.end()) continue;
lazy_from_entry(packet->second, response);
ret = verify_message(&response, put_immutable_item_desc, parsed, 7, error_string, sizeof(error_string));
ret = verify_message(response, put_immutable_item_desc, parsed, 7
, error_string, sizeof(error_string));
if (ret)
{
TEST_EQUAL(parsed[0]->string_value(), "q");
TEST_EQUAL(parsed[2]->string_value(), "put");
std::pair<const char*, int> v = parsed[6]->data_section();
TEST_EQUAL(parsed[0].string_value(), "q");
TEST_EQUAL(parsed[2].string_value(), "put");
std::pair<const char*, int> v = parsed[6].data_section();
TEST_EQUAL(v.second, itemv.second);
TEST_CHECK(memcmp(v.first, itemv.first, itemv.second) == 0);
char t[10];
snprintf(t, sizeof(t), "%02d", i);
TEST_EQUAL(parsed[5]->string_value(), t);
if (parsed[0]->string_value() != "q" || parsed[2]->string_value() != "put") continue;
TEST_EQUAL(parsed[5].string_value(), t);
if (parsed[0].string_value() != "q" || parsed[2].string_value() != "put") continue;
}
else
{
@ -1827,7 +1857,8 @@ int test_main()
if (packet == g_sent_packets.end()) continue;
lazy_from_entry(packet->second, response);
ret = verify_message(&response, get_item_desc, parsed, 6, error_string, sizeof(error_string));
ret = verify_message(response, get_item_desc, parsed, 6
, error_string, sizeof(error_string));
if (!ret)
{
fprintf(stderr, " invalid mutable put request: %s\n", print_entry(response).c_str());
@ -1854,21 +1885,22 @@ int test_main()
if (packet == g_sent_packets.end()) continue;
lazy_from_entry(packet->second, response);
ret = verify_message(&response, put_mutable_item_desc, parsed, 11, error_string, sizeof(error_string));
ret = verify_message(response, put_mutable_item_desc, parsed, 11
, error_string, sizeof(error_string));
if (ret)
{
TEST_EQUAL(parsed[0]->string_value(), "q");
TEST_EQUAL(parsed[2]->string_value(), "put");
TEST_EQUAL(parsed[6]->string_value(), std::string(public_key, item_pk_len));
TEST_EQUAL(parsed[7]->int_value(), seq);
TEST_EQUAL(parsed[8]->string_value(), sig);
std::pair<const char*, int> v = parsed[10]->data_section();
TEST_EQUAL(parsed[0].string_value(), "q");
TEST_EQUAL(parsed[2].string_value(), "put");
TEST_EQUAL(parsed[6].string_value(), std::string(public_key, item_pk_len));
TEST_EQUAL(parsed[7].int_value(), seq);
TEST_EQUAL(parsed[8].string_value(), sig);
std::pair<const char*, int> v = parsed[10].data_section();
TEST_EQUAL(v.second, itemv.second);
TEST_CHECK(memcmp(v.first, itemv.first, itemv.second) == 0);
char t[10];
snprintf(t, sizeof(t), "%02d", i);
TEST_EQUAL(parsed[9]->string_value(), t);
if (parsed[0]->string_value() != "q" || parsed[2]->string_value() != "put") continue;
TEST_EQUAL(parsed[9].string_value(), t);
if (parsed[0].string_value() != "q" || parsed[2].string_value() != "put") continue;
}
else
{

View File

@ -37,7 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/alloca.hpp"
#include "libtorrent/time.hpp"
#include "libtorrent/peer_info.hpp"
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/bdecode.hpp"
#include <cstring>
#include <boost/bind.hpp>
#include <iostream>
@ -476,20 +476,26 @@ void test_dont_have()
int ext_msg = recv_buffer[1];
if (ext_msg != 0) continue;
lazy_entry e;
bdecode_node e;
error_code ec;
int ret = lazy_bdecode(recv_buffer + 2, recv_buffer + len, e, ec);
int pos = 0;
int ret = bdecode(recv_buffer + 2, recv_buffer + len, e, ec, &pos);
if (ret != 0)
{
fprintf(stderr, "failed to parse extension handshake: %s at pos %d\n"
, ec.message().c_str(), pos);
}
TEST_EQUAL(ret, 0);
printf("extension handshake: %s\n", print_entry(e).c_str());
lazy_entry const* m = e.dict_find_dict("m");
bdecode_node m = e.dict_find_dict("m");
TEST_CHECK(m);
if (!m) return;
lazy_entry const* dont_have = m->dict_find_int("lt_donthave");
bdecode_node dont_have = m.dict_find_int("lt_donthave");
TEST_CHECK(dont_have);
if (!dont_have) return;
lt_dont_have = dont_have->int_value();
lt_dont_have = dont_have.int_value();
}
char* ptr = recv_buffer;

View File

@ -169,8 +169,8 @@ int test_main()
std::vector<char> buf;
bencode(std::back_inserter(buf), session_state);
lazy_entry session_state2;
int ret = lazy_bdecode(&buf[0], &buf[0] + buf.size(), session_state2, ec);
bdecode_node session_state2;
int ret = bdecode(&buf[0], &buf[0] + buf.size(), session_state2, ec);
TEST_CHECK(ret == 0);
fprintf(stderr, "session_state\n%s\n", print_entry(session_state2).c_str());
@ -204,7 +204,8 @@ int test_main()
#endif
// make sure settings that haven't been changed from their defaults are not saved
TEST_CHECK(session_state2.dict_find("settings")->dict_find("optimistic_disk_retry") == 0);
TEST_CHECK(session_state2.dict_find("settings")
.dict_find("optimistic_disk_retry") == 0);
s->load_state(session_state2);

View File

@ -86,12 +86,12 @@ int test_main()
#endif
char const eplist[] = "l6:\x10\x05\x80\x01\x05\x39" "18:\x10\0\0\0\0\0\0\0\0\0\0\0\0\0\xff\xff\x05\x39" "e";
lazy_entry e;
bdecode_node e;
error_code ec;
lazy_bdecode(eplist, eplist + sizeof(eplist)-1, e, ec);
bdecode(eplist, eplist + sizeof(eplist)-1, e, ec);
TEST_CHECK(!ec);
std::vector<udp::endpoint> list;
read_endpoint_list<udp::endpoint>(&e, list);
read_endpoint_list<udp::endpoint>(e, list);
#if TORRENT_USE_IPV6
TEST_EQUAL(list.size(), 2);

View File

@ -459,7 +459,7 @@ void test_check_files(std::string const& test_path
libtorrent::mutex lock;
bool done = false;
lazy_entry frd;
bdecode_node frd;
io.async_check_fastresume(pm.get(), &frd, boost::bind(&on_check_resume_data, _1, &done));
io.submit_jobs();
ios.reset();

View File

@ -177,9 +177,9 @@ int main(int argc, char* argv[])
state.resize(size);
fread(&state[0], 1, state.size(), f);
lazy_entry e;
bdecode_node e;
error_code ec;
lazy_bdecode(&state[0], &state[0] + state.size(), e, ec);
bdecode(&state[0], &state[0] + state.size(), e, ec);
if (ec)
fprintf(stderr, "failed to parse .dht file: (%d) %s\n"
, ec.value(), ec.message().c_str());

View File

@ -34,11 +34,11 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/cstdint.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/bdecode.hpp"
#include "libtorrent/torrent_info.hpp"
#include "libtorrent/error_code.hpp"
using libtorrent::lazy_entry;
using libtorrent::bdecode_node;
using boost::random::mt19937;
using boost::random::uniform_int_distribution;
@ -233,52 +233,52 @@ void render_arbitrary_item(std::string& out)
}
}
void render_variant(std::string& out, lazy_entry const& e)
void render_variant(std::string& out, bdecode_node const& e)
{
switch (e.type())
{
case lazy_entry::dict_t:
case bdecode_node::dict_t:
print_dict(out);
for (int i = 0; i < e.dict_size(); ++i)
{
std::pair<std::string, lazy_entry const*> item = e.dict_at(i);
std::pair<std::string, bdecode_node> item = e.dict_at(i);
const bool duplicate = g_seed == 1;
const bool skipped = g_seed == 2;
g_seed -= 2;
if (duplicate)
{
print_string(out, item.first);
render_variant(out, *item.second);
render_variant(out, item.second);
}
if (!skipped)
{
print_string(out, item.first);
render_variant(out, *item.second);
render_variant(out, item.second);
}
render_arbitrary_item(out);
}
print_terminate(out);
break;
case lazy_entry::list_t:
case bdecode_node::list_t:
print_list(out);
for (int i = 0; i < e.list_size(); ++i)
{
const bool duplicate = g_seed == 1;
const bool skipped = g_seed == 2;
g_seed -= 2;
if (duplicate) render_variant(out, *e.list_at(i));
if (duplicate) render_variant(out, e.list_at(i));
render_arbitrary_item(out);
if (!skipped) render_variant(out, *e.list_at(i));
if (!skipped) render_variant(out, e.list_at(i));
}
print_terminate(out);
break;
case lazy_entry::int_t:
case bdecode_node::int_t:
print_int(out, e.int_value());
break;
case lazy_entry::string_t:
case bdecode_node::string_t:
print_string(out, e.string_value());
break;
default:
@ -371,8 +371,8 @@ int main(int argc, char const* argv[])
continue;
}
lazy_entry e;
if (buf.size() == 0 || lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec) != 0)
bdecode_node e;
if (buf.size() == 0 || bdecode(&buf[0], &buf[0] + buf.size(), e, ec) != 0)
{
fprintf(stderr, "ERROR parsing file: %s\n%s\n"
, *argv, ec.message().c_str());

View File

@ -3,10 +3,15 @@
OBJECT_PATH=bin/gcc-4.8/debug/asserts-off/boost-source/debug-iterators-on/export-extra-on/invariant-checks-off/link-static/logging-on/test-coverage-on/threading-multi/src
function run_test {
set +e
rm $OBJECT_PATH/*.gcda
set -e
cd test
set +e
rm -rf bin
set -e
bjam asserts=off invariant-checks=off link=static boost=source test-coverage=on picker-debugging=off -j4 $1
cd ..
@ -20,11 +25,16 @@ function run_test {
# force rebuilding and rerunning the unit tests
cd test
set +e
rm -rf bin
set -e
cd ..
set +e
mkdir test-coverage
set -e
run_test test_bdecode "*/bdecode.*"
run_test test_piece_picker "*/piece_picker.*"
run_test test_torrent_info "*/torrent_info.*"
run_test test_part_file "*/part_file.*"
@ -40,5 +50,3 @@ run_test test_sliding_average "*/sliding_average.*"
run_test test_string "*/escape_string.*"
run_test test_utf8 "*/ConvertUTF.*"