mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-10-07 22:59:21 +00:00
* Added a missing READ_PORT case to a switch in handshake.cc.
* Stuff. git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@1164 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
@@ -85,7 +85,13 @@ command_base_call_value(Command* rawCommand, target_type target, const torrent::
|
||||
return command_base_call_value_base<T>(rawCommand, target, rawArgs, 0, 1);
|
||||
}
|
||||
|
||||
template <typename T> const torrent::Object
|
||||
command_base_call_value_kb(Command* rawCommand, target_type target, const torrent::Object& rawArgs) {
|
||||
return command_base_call_value_base<T>(rawCommand, target, rawArgs, 0, 1024);
|
||||
}
|
||||
|
||||
COMMAND_BASE_TEMPLATE_DEFINE(command_base_call_value);
|
||||
COMMAND_BASE_TEMPLATE_DEFINE(command_base_call_value_kb);
|
||||
|
||||
template <typename T> const torrent::Object
|
||||
command_base_call_string(Command* rawCommand, target_type target, const torrent::Object& rawArgs) {
|
||||
|
||||
@@ -117,6 +117,7 @@ COMMAND_BASE_TEMPLATE_TYPE(command_list_function, torrent::Object (T, const to
|
||||
|
||||
COMMAND_BASE_TEMPLATE_CALL(command_base_call, command_function);
|
||||
COMMAND_BASE_TEMPLATE_CALL(command_base_call_value, command_value_function);
|
||||
COMMAND_BASE_TEMPLATE_CALL(command_base_call_value_kb, command_value_function);
|
||||
COMMAND_BASE_TEMPLATE_CALL(command_base_call_string, command_string_function);
|
||||
COMMAND_BASE_TEMPLATE_CALL(command_base_call_list, command_list_function);
|
||||
|
||||
|
||||
@@ -38,6 +38,72 @@
|
||||
|
||||
#include "object_storage.h"
|
||||
|
||||
#include "parse.h"
|
||||
|
||||
namespace rpc {
|
||||
|
||||
object_storage::local_iterator
|
||||
object_storage::find_local(const torrent::raw_string& key) {
|
||||
std::size_t n = hash_fixed_key_type::hash(key.data(), key.size()) % bucket_count();
|
||||
|
||||
for (local_iterator itr = begin(n), last = end(n); itr != last; itr++)
|
||||
if (itr->first.size() == key.size() && std::memcmp(itr->first.data(), key.data(), key.size()) == 0)
|
||||
return itr;
|
||||
|
||||
return end(bucket_count());
|
||||
}
|
||||
|
||||
object_storage::iterator
|
||||
object_storage::insert(const char* key_data, uint32_t key_size, const torrent::Object& object, unsigned int flags) {
|
||||
if (std::find(key_data, key_data + key_size, '\0') != key_data + key_size)
|
||||
throw torrent::input_error("Found nul-char in string.");
|
||||
|
||||
// Check for size > key_size.
|
||||
// Check for empty string.
|
||||
|
||||
// Ensure the object type is correct.
|
||||
|
||||
if (!(flags & mask_type))
|
||||
throw torrent::input_error("No type flags set when calling object_storage::insert.");
|
||||
|
||||
std::pair<iterator, bool> result = base_type::insert(std::make_pair(key_type(key_data, key_size), object_storage_node()));
|
||||
|
||||
if (!result.second)
|
||||
throw torrent::input_error("Key already exists in object_storage.");
|
||||
|
||||
result.first->second.object = object;
|
||||
result.first->second.flags = flags;
|
||||
|
||||
return result.first;
|
||||
}
|
||||
|
||||
const torrent::Object&
|
||||
object_storage::get(const torrent::raw_string& key) {
|
||||
local_iterator itr = find_local(key);
|
||||
|
||||
if (itr == end(bucket_count()))
|
||||
throw torrent::input_error("Key not found.");
|
||||
|
||||
return itr->second.object;
|
||||
}
|
||||
|
||||
const torrent::Object&
|
||||
object_storage::set(const torrent::raw_string& key, const torrent::Object& object) {
|
||||
local_iterator itr = find_local(key);
|
||||
|
||||
if (itr == end(bucket_count()))
|
||||
throw torrent::input_error("Key not found.");
|
||||
|
||||
// Redo this...
|
||||
|
||||
switch (itr->second.flags & mask_type) {
|
||||
case flag_generic_type: itr->second.object = object; break;
|
||||
case flag_value_type: itr->second.object = convert_to_value(object); break;
|
||||
case flag_string_type: itr->second.object = convert_to_string(object); break;
|
||||
default: throw torrent::internal_error("object_storage::set: Type not set.");
|
||||
}
|
||||
|
||||
return itr->second.object;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+171
-28
@@ -42,7 +42,7 @@
|
||||
#define RTORRENT_RPC_OBJECT_STORAGE_H
|
||||
|
||||
#include <cstring>
|
||||
#include <tr1/unordered_set>
|
||||
#include <tr1/unordered_map>
|
||||
#include <torrent/object.h>
|
||||
|
||||
namespace rpc {
|
||||
@@ -50,42 +50,185 @@ namespace rpc {
|
||||
// The key size should be such that the value type size which includes
|
||||
// the next-pointer.
|
||||
|
||||
struct object_storage_node_internal {
|
||||
template <size_t MaxSize>
|
||||
class fixed_key_type {
|
||||
public:
|
||||
typedef char value_type;
|
||||
typedef const char* iterator;
|
||||
typedef const char* const_iterator;
|
||||
typedef uint32_t size_type;
|
||||
|
||||
static const size_type max_size = MaxSize - 1;
|
||||
|
||||
fixed_key_type() : m_size(0) { m_data[0] = '\0'; }
|
||||
fixed_key_type(const fixed_key_type& k) : m_size(k.m_size) { std::memcpy(m_data, k.m_data, k.m_size + 1); }
|
||||
|
||||
fixed_key_type(const value_type* src_data, size_type src_size) { set_data(src_data, src_size); }
|
||||
|
||||
static fixed_key_type from_c_str(const char* str) { fixed_key_type k; k.set_c_str(str); return k; }
|
||||
static fixed_key_type from_string(const std::string& str) { fixed_key_type k; k.set_c_str(str.c_str(), str.size()); return k; }
|
||||
static fixed_key_type from_raw_string(const torrent::raw_string& str) { fixed_key_type k; k.set_data(str.data(), str.size()); return k; }
|
||||
|
||||
bool empty() const { return m_size == 0;; }
|
||||
size_type size() const { return m_size; }
|
||||
|
||||
iterator begin() const { return m_data; }
|
||||
iterator end() const { return m_data + m_size; }
|
||||
|
||||
value_type* data() { return m_data; }
|
||||
const value_type* data() const { return m_data; }
|
||||
const char* c_str() const { return m_data; }
|
||||
|
||||
void set_data(const value_type* src_data, size_type src_size);
|
||||
void set_c_str(const value_type* src_data);
|
||||
void set_c_str(const value_type* src_data, size_type src_size);
|
||||
|
||||
bool operator == (const fixed_key_type& rhs) const { return m_size == rhs.m_size && std::memcmp(m_data, rhs.m_data, m_size) == 0; }
|
||||
bool operator != (const fixed_key_type& rhs) const { return m_size != rhs.m_size || std::memcmp(m_data, rhs.m_data, m_size) != 0; }
|
||||
|
||||
bool operator == (const std::string& rhs) const { return m_size == rhs.size() && std::memcmp(m_data, rhs.data(), m_size) == 0; }
|
||||
|
||||
private:
|
||||
size_type m_size;
|
||||
char m_data[max_size];
|
||||
};
|
||||
|
||||
struct hash_fixed_key_type {
|
||||
template <size_t MaxSize>
|
||||
inline std::size_t operator () (const fixed_key_type<MaxSize>& p) const { return hash(p.data()); }
|
||||
|
||||
static inline std::size_t hash(const char* data) {
|
||||
std::size_t result = 0;
|
||||
|
||||
while (*data != '\0')
|
||||
result = (result * 131) + *data++;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline std::size_t hash(const char* data, uint32_t size) {
|
||||
std::size_t result = 0;
|
||||
|
||||
while (size--)
|
||||
result = (result * 131) + *data++;
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
struct object_storage_node {
|
||||
torrent::Object object;
|
||||
char key[0];
|
||||
char flags;
|
||||
};
|
||||
|
||||
struct object_storage_node : public object_storage_node_internal {
|
||||
// TODO: Use the size of the unordered_map::value_type with a struct {}.
|
||||
static const size_t key_size = 128 - sizeof(object_storage_node_internal) - sizeof(void*);
|
||||
};
|
||||
|
||||
struct hash_object_storage_node {
|
||||
inline std::size_t operator () (const object_storage_node& p);
|
||||
};
|
||||
|
||||
bool operator == (const object_storage_node& left, const object_storage_node& right) { return std::strcmp(left.key, right.key) == 0; }
|
||||
bool operator != (const object_storage_node& left, const object_storage_node& right) { return std::strcmp(left.key, right.key) != 0; }
|
||||
bool operator < (const object_storage_node& left, const object_storage_node& right) { return std::strcmp(left.key, right.key) < 0; }
|
||||
bool operator <= (const object_storage_node& left, const object_storage_node& right) { return std::strcmp(left.key, right.key) <= 0; }
|
||||
bool operator > (const object_storage_node& left, const object_storage_node& right) { return std::strcmp(left.key, right.key) > 0; }
|
||||
bool operator >= (const object_storage_node& left, const object_storage_node& right) { return std::strcmp(left.key, right.key) >= 0; }
|
||||
|
||||
class object_storage : private std::tr1::unordered_set<object_storage_node, hash_object_storage_node> {
|
||||
typedef std::tr1::unordered_set<object_storage_node, hash_object_storage_node> base_type;
|
||||
class object_storage : private std::tr1::unordered_map<fixed_key_type<64>, object_storage_node, hash_fixed_key_type> {
|
||||
public:
|
||||
typedef std::tr1::unordered_map<fixed_key_type<64>, object_storage_node, hash_fixed_key_type> base_type;
|
||||
|
||||
using base_type::key_type;
|
||||
using base_type::value_type;
|
||||
using base_type::iterator;
|
||||
using base_type::const_iterator;
|
||||
using base_type::local_iterator;
|
||||
using base_type::const_local_iterator;
|
||||
|
||||
using base_type::begin;
|
||||
using base_type::end;
|
||||
using base_type::size;
|
||||
using base_type::empty;
|
||||
using base_type::key_eq;
|
||||
using base_type::bucket;
|
||||
using base_type::bucket_count;
|
||||
using base_type::max_bucket_count;
|
||||
using base_type::load_factor;
|
||||
|
||||
using base_type::clear;
|
||||
using base_type::find;
|
||||
using base_type::erase;
|
||||
|
||||
static const unsigned int flag_generic_type = 0x1;
|
||||
static const unsigned int flag_value_type = 0x2;
|
||||
static const unsigned int flag_string_type = 0x4;
|
||||
static const unsigned int flag_last_type = 0x8;
|
||||
|
||||
static const unsigned int mask_type = flag_last_type - 1;
|
||||
|
||||
static const size_t key_size = key_type::max_size;
|
||||
|
||||
local_iterator find_local(const torrent::raw_string& key);
|
||||
|
||||
iterator insert(const char* key_data, uint32_t key_size, const torrent::Object& object, unsigned int flags);
|
||||
|
||||
iterator insert(const char* key, const torrent::Object& object, unsigned int flags);
|
||||
iterator insert(const torrent::raw_string& key, const torrent::Object& object, unsigned int flags);
|
||||
iterator insert_string(const std::string& key, const torrent::Object& object, unsigned int flags);
|
||||
|
||||
// Access functions that throw on error.
|
||||
|
||||
const torrent::Object& get(const torrent::raw_string& key);
|
||||
const torrent::Object& get_c_str(const char* str) { return get(torrent::raw_string(str, std::strlen(str))); }
|
||||
|
||||
const torrent::Object& set(const torrent::raw_string& key, const torrent::Object& object);
|
||||
|
||||
const torrent::Object& set_c_str(const char* str, const torrent::Object& object) { return set(torrent::raw_string(str, std::strlen(str)), object); }
|
||||
};
|
||||
|
||||
inline std::size_t
|
||||
hash_object_storage_node::operator () (const object_storage_node& p) {
|
||||
std::size_t result = 0;
|
||||
const char* first = p.key;
|
||||
//
|
||||
// Implementation:
|
||||
//
|
||||
|
||||
while (*first != '\0')
|
||||
result = (result * 131) + *first++;
|
||||
template <size_t MaxSize> inline void
|
||||
fixed_key_type<MaxSize>::set_data(const value_type* src_data, size_type src_size) {
|
||||
if (src_size >= max_size) {
|
||||
new (this) fixed_key_type();
|
||||
return;
|
||||
}
|
||||
|
||||
return result;
|
||||
m_size = src_size;
|
||||
std::memcpy(m_data, src_data, m_size);
|
||||
m_data[m_size] = '\0';
|
||||
}
|
||||
|
||||
template <size_t MaxSize> inline void
|
||||
fixed_key_type<MaxSize>::set_c_str(const value_type* src_data) {
|
||||
value_type* itr = m_data;
|
||||
const value_type* last = m_data + max_size;
|
||||
|
||||
while (itr != last && *src_data != '\0')
|
||||
*itr++ = *src_data++;
|
||||
|
||||
*itr = '\0';
|
||||
m_size = std::distance(m_data, itr);
|
||||
}
|
||||
|
||||
template <size_t MaxSize> inline void
|
||||
fixed_key_type<MaxSize>::set_c_str(const value_type* src_data, size_type src_size) {
|
||||
if (src_size >= max_size) {
|
||||
new (this) fixed_key_type();
|
||||
return;
|
||||
}
|
||||
|
||||
m_size = src_size;
|
||||
std::memcpy(m_data, src_data, m_size + 1);
|
||||
}
|
||||
|
||||
inline object_storage::iterator
|
||||
object_storage::insert(const char* key, const torrent::Object& object, unsigned int flags) {
|
||||
return insert(key, std::strlen(key), object, flags);
|
||||
}
|
||||
|
||||
inline object_storage::iterator
|
||||
object_storage::insert(const torrent::raw_string& key, const torrent::Object& object, unsigned int flags) {
|
||||
return insert(key.data(), key.size(), object, flags);
|
||||
}
|
||||
|
||||
inline object_storage::iterator
|
||||
object_storage::insert_string(const std::string& key, const torrent::Object& object, unsigned int flags) {
|
||||
return insert(key.data(), key.size(), object, flags);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+39
-4
@@ -228,6 +228,33 @@ parse_whole_list(const char* first, const char* last, torrent::Object* dest, boo
|
||||
return first;
|
||||
}
|
||||
|
||||
std::string
|
||||
convert_to_string(const torrent::Object& rawSrc) {
|
||||
const torrent::Object& src = convert_to_single_argument(rawSrc);
|
||||
|
||||
switch (src.type()) {
|
||||
case torrent::Object::TYPE_VALUE: {
|
||||
char buffer[64];
|
||||
snprintf(buffer, 64, "%lli", src.as_value());
|
||||
return std::string(buffer);
|
||||
}
|
||||
case torrent::Object::TYPE_STRING: return src.as_string();
|
||||
case torrent::Object::TYPE_NONE: return std::string();
|
||||
|
||||
case torrent::Object::TYPE_RAW_BENCODE:
|
||||
if (src.as_raw_bencode().is_empty())
|
||||
return std::string();
|
||||
|
||||
if (src.as_raw_bencode().is_raw_string())
|
||||
return src.as_raw_bencode().as_raw_string().as_string();
|
||||
|
||||
if (src.as_raw_bencode().is_value())
|
||||
return src.as_raw_bencode().as_value_string();
|
||||
|
||||
default: throw torrent::input_error("Not a string.");
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
convert_list_to_string(const torrent::Object& src) {
|
||||
if (!src.is_list())
|
||||
@@ -334,12 +361,20 @@ convert_to_value_nothrow(const torrent::Object& src, int64_t* value, int base, i
|
||||
break;
|
||||
|
||||
case torrent::Object::TYPE_STRING:
|
||||
if (parse_skip_wspace(parse_value(unpacked.as_string().c_str(), value, base, unit),
|
||||
unpacked.as_string().c_str() + unpacked.as_string().size()) != unpacked.as_string().c_str() + unpacked.as_string().size())
|
||||
return false;
|
||||
return parse_skip_wspace(parse_value(unpacked.as_string().c_str(), value, base, unit),
|
||||
unpacked.as_string().c_str() + unpacked.as_string().size())
|
||||
== unpacked.as_string().c_str() + unpacked.as_string().size();
|
||||
|
||||
break;
|
||||
case torrent::Object::TYPE_RAW_STRING: {
|
||||
const torrent::raw_string& str = src.as_raw_string();
|
||||
|
||||
char buffer[str.size() + 1];
|
||||
std::memcpy(buffer, str.data(), str.size());
|
||||
buffer[str.size()] = '\0';
|
||||
|
||||
return parse_skip_wspace(parse_value(buffer, value, base, unit), buffer + str.size())
|
||||
== buffer + str.size();
|
||||
}
|
||||
case torrent::Object::TYPE_NONE:
|
||||
*value = 0;
|
||||
break;
|
||||
|
||||
@@ -73,6 +73,7 @@ void parse_whole_string(const char* first, const char* last, std::string*
|
||||
|
||||
const char* parse_value(const char* src, int64_t* value, int base = 0, int unit = 1);
|
||||
const char* parse_value_nothrow(const char* src, int64_t* value, int base = 0, int unit = 1);
|
||||
const char* parse_value_nothrow(const char* first, const char* last, int64_t* value, int base = 0, int unit = 0);
|
||||
|
||||
void parse_whole_value(const char* src, int64_t* value, int base = 0, int unit = 1);
|
||||
bool parse_whole_value_nothrow(const char* src, int64_t* value, int base = 0, int unit = 1);
|
||||
@@ -81,6 +82,8 @@ const char* parse_object (const char* first, const char* last, torrent::Objec
|
||||
const char* parse_list (const char* first, const char* last, torrent::Object* dest, bool (*delim)(const char) = &parse_is_delim_default);
|
||||
const char* parse_whole_list(const char* first, const char* last, torrent::Object* dest, bool (*delim)(const char) = &parse_is_delim_default);
|
||||
|
||||
std::string convert_to_string(const torrent::Object& src);
|
||||
|
||||
std::string convert_list_to_string(const torrent::Object& src);
|
||||
std::string convert_list_to_string(torrent::Object::list_const_iterator first, torrent::Object::list_const_iterator last);
|
||||
std::string convert_list_to_command(torrent::Object::list_const_iterator first, torrent::Object::list_const_iterator last);
|
||||
|
||||
Reference in New Issue
Block a user