mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-08-17 07:32:32 +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:
@@ -313,8 +313,6 @@ void
|
||||
initialize_command_events() {
|
||||
CMD2_ANY("test.thread_locking", std::tr1::bind(&test_thread_locking));
|
||||
|
||||
CMD2_VAR_BOOL ("pieces.hash.on_completion", true);
|
||||
|
||||
CMD2_ANY_STRING ("on_ratio", std::tr1::bind(&apply_on_ratio, std::tr1::placeholders::_2));
|
||||
|
||||
CMD2_ANY ("start_tied", std::tr1::bind(&apply_start_tied));
|
||||
@@ -322,8 +320,11 @@ initialize_command_events() {
|
||||
CMD2_ANY ("close_untied", std::tr1::bind(&apply_close_untied));
|
||||
CMD2_ANY ("remove_untied", std::tr1::bind(&apply_remove_untied));
|
||||
|
||||
CMD2_ANY_LIST ("schedule", std::tr1::bind(&apply_schedule, std::tr1::placeholders::_2));
|
||||
CMD2_ANY_STRING_V("schedule_remove", std::tr1::bind(&rpc::CommandScheduler::erase_str, control->command_scheduler(), std::tr1::placeholders::_2));
|
||||
CMD2_ANY_LIST ("schedule2", std::tr1::bind(&apply_schedule, std::tr1::placeholders::_2));
|
||||
CMD2_ANY_STRING_V("schedule_remove2", std::tr1::bind(&rpc::CommandScheduler::erase_str, control->command_scheduler(), std::tr1::placeholders::_2));
|
||||
|
||||
CMD2_REDIRECT_GENERIC("schedule", "schedule2");
|
||||
CMD2_REDIRECT_GENERIC("schedule_remove", "schedule_remove2");
|
||||
|
||||
CMD2_ANY_STRING_V("import", std::tr1::bind(&apply_import, std::tr1::placeholders::_2));
|
||||
CMD2_ANY_STRING_V("try_import", std::tr1::bind(&apply_try_import, std::tr1::placeholders::_2));
|
||||
|
||||
@@ -79,6 +79,7 @@ void initialize_commands();
|
||||
|
||||
#define CMD2_ANY_VALUE(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<rpc::target_type>, slot, "i:i", "")
|
||||
#define CMD2_ANY_VALUE_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_value<rpc::target_type>, object_convert_void(slot), "i:i", "")
|
||||
#define CMD2_ANY_VALUE_KB(key, slot) CMD2_A_FUNCTION(key, command_base_call_value_kb<rpc::target_type>, object_convert_void(slot), "i:i", "")
|
||||
|
||||
#define CMD2_ANY_STRING(key, slot) CMD2_A_FUNCTION(key, command_base_call_string<rpc::target_type>, slot, "i:s", "")
|
||||
#define CMD2_ANY_STRING_V(key, slot) CMD2_A_FUNCTION(key, command_base_call_string<rpc::target_type>, object_convert_void(slot), "i:s", "")
|
||||
@@ -125,9 +126,13 @@ void initialize_commands();
|
||||
|
||||
#define CMD2_REDIRECT(from_key, to_key) \
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc);
|
||||
|
||||
#define CMD2_REDIRECT_GENERIC(from_key, to_key) \
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_no_target);
|
||||
#define CMD2_REDIRECT_FILE(from_key, to_key) \
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_file_target);
|
||||
#define CMD2_REDIRECT_TRACKER(from_key, to_key) \
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_tracker_target);
|
||||
|
||||
|
||||
//
|
||||
// Conversion of return types:
|
||||
|
||||
@@ -224,6 +224,8 @@ initialize_command_local() {
|
||||
CMD2_ANY ("pieces.stats_preloaded", std::tr1::bind(&CM_t::stats_preloaded, chunkManager));
|
||||
CMD2_ANY ("pieces.stats_not_preloaded", std::tr1::bind(&CM_t::stats_not_preloaded, chunkManager));
|
||||
|
||||
CMD2_VAR_BOOL ("pieces.hash.on_completion", true);
|
||||
|
||||
CMD2_VAR_STRING ("directory.default", "./");
|
||||
|
||||
// TODO: Clean up.
|
||||
|
||||
+10
-8
@@ -434,14 +434,16 @@ initialize_command_network() {
|
||||
CMD2_VAR_VALUE("max_downloads_global", 0);
|
||||
|
||||
// TODO: Move the logic into some libtorrent function.
|
||||
CMD2_ANY ("throttle.global_up.rate", std::tr1::bind(&torrent::Rate::rate, torrent::up_rate()));
|
||||
CMD2_ANY ("throttle.global_up.total", std::tr1::bind(&torrent::Rate::total, torrent::up_rate()));
|
||||
CMD2_ANY ("throttle.global_up.max_rate", std::tr1::bind(&torrent::Throttle::max_rate, torrent::up_throttle_global()));
|
||||
CMD2_ANY_VALUE_V ("throttle.global_up.max_rate.set", std::tr1::bind(&ui::Root::set_up_throttle_i64, control->ui(), std::tr1::placeholders::_2));
|
||||
CMD2_ANY ("throttle.global_down.rate", std::tr1::bind(&torrent::Rate::rate, torrent::down_rate()));
|
||||
CMD2_ANY ("throttle.global_down.total", std::tr1::bind(&torrent::Rate::total, torrent::down_rate()));
|
||||
CMD2_ANY ("throttle.global_down.max_rate", std::tr1::bind(&torrent::Throttle::max_rate, torrent::down_throttle_global()));
|
||||
CMD2_ANY_VALUE_V ("throttle.global_down.max_rate.set", std::tr1::bind(&ui::Root::set_down_throttle_i64, control->ui(), std::tr1::placeholders::_2));
|
||||
CMD2_ANY ("throttle.global_up.rate", std::tr1::bind(&torrent::Rate::rate, torrent::up_rate()));
|
||||
CMD2_ANY ("throttle.global_up.total", std::tr1::bind(&torrent::Rate::total, torrent::up_rate()));
|
||||
CMD2_ANY ("throttle.global_up.max_rate", std::tr1::bind(&torrent::Throttle::max_rate, torrent::up_throttle_global()));
|
||||
CMD2_ANY_VALUE_V ("throttle.global_up.max_rate.set", std::tr1::bind(&ui::Root::set_up_throttle_i64, control->ui(), std::tr1::placeholders::_2));
|
||||
CMD2_ANY_VALUE_KB("throttle.global_up.max_rate.set_kb", std::tr1::bind(&ui::Root::set_up_throttle_i64, control->ui(), std::tr1::placeholders::_2));
|
||||
CMD2_ANY ("throttle.global_down.rate", std::tr1::bind(&torrent::Rate::rate, torrent::down_rate()));
|
||||
CMD2_ANY ("throttle.global_down.total", std::tr1::bind(&torrent::Rate::total, torrent::down_rate()));
|
||||
CMD2_ANY ("throttle.global_down.max_rate", std::tr1::bind(&torrent::Throttle::max_rate, torrent::down_throttle_global()));
|
||||
CMD2_ANY_VALUE_V ("throttle.global_down.max_rate.set", std::tr1::bind(&ui::Root::set_down_throttle_i64, control->ui(), std::tr1::placeholders::_2));
|
||||
CMD2_ANY_VALUE_KB("throttle.global_down.max_rate.set_kb", std::tr1::bind(&ui::Root::set_down_throttle_i64, control->ui(), std::tr1::placeholders::_2));
|
||||
|
||||
CMD2_ANY_LIST("throttle_up", std::tr1::bind(&apply_throttle, std::tr1::placeholders::_2, true));
|
||||
CMD2_ANY_LIST("throttle_down", std::tr1::bind(&apply_throttle, std::tr1::placeholders::_2, false));
|
||||
|
||||
+30
-39
@@ -65,6 +65,7 @@
|
||||
#include "utils/directory.h"
|
||||
|
||||
#include "control.h"
|
||||
#include "command_helpers.h"
|
||||
#include "globals.h"
|
||||
#include "signal_handler.h"
|
||||
#include "option_parser.h"
|
||||
@@ -321,16 +322,6 @@ main(int argc, char** argv) {
|
||||
// * command_tracker.cc
|
||||
// * command_ui.cc
|
||||
|
||||
#define CMD2_REDIRECT(from_key, to_key) \
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc);
|
||||
|
||||
#define CMD2_REDIRECT_GENERIC(from_key, to_key) \
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_no_target);
|
||||
#define CMD2_REDIRECT_FILE(from_key, to_key) \
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_file_target);
|
||||
#define CMD2_REDIRECT_TRACKER(from_key, to_key) \
|
||||
rpc::commands.create_redirect(from_key, to_key, rpc::CommandMap::flag_public_xmlrpc | rpc::CommandMap::flag_tracker_target);
|
||||
|
||||
CMD2_REDIRECT_GENERIC("system.method.insert", "method.insert");
|
||||
CMD2_REDIRECT_GENERIC("system.method.erase", "method.erase");
|
||||
CMD2_REDIRECT_GENERIC("system.method.get", "method.get");
|
||||
@@ -340,26 +331,26 @@ main(int argc, char** argv) {
|
||||
CMD2_REDIRECT_GENERIC("system.method.set_key", "method.set_key");
|
||||
|
||||
CMD2_REDIRECT ("get_handshake_log", "log.handshake");
|
||||
CMD2_REDIRECT ("set_handshake_log", "log.handshake.set");
|
||||
CMD2_REDIRECT_GENERIC("set_handshake_log", "log.handshake.set");
|
||||
CMD2_REDIRECT ("get_log.tracker", "log.tracker");
|
||||
CMD2_REDIRECT ("set_log.tracker", "log.tracker.set");
|
||||
CMD2_REDIRECT_GENERIC("set_log.tracker", "log.tracker.set");
|
||||
|
||||
CMD2_REDIRECT ("get_name", "system.session_name");
|
||||
CMD2_REDIRECT ("set_name", "system.session_name.set");
|
||||
CMD2_REDIRECT_GENERIC("set_name", "system.session_name.set");
|
||||
|
||||
CMD2_REDIRECT ("system.file_allocate", "system.file.allocate");
|
||||
CMD2_REDIRECT ("system.file_allocate.set", "system.file.allocate.set");
|
||||
CMD2_REDIRECT ("get_max_file_size", "system.file.max_size");
|
||||
CMD2_REDIRECT ("set_max_file_size", "system.file.max_size.set");
|
||||
CMD2_REDIRECT_GENERIC("set_max_file_size", "system.file.max_size.set");
|
||||
CMD2_REDIRECT ("get_split_file_size", "system.file.split_size");
|
||||
CMD2_REDIRECT ("set_split_file_size", "system.file.split_size.set");
|
||||
CMD2_REDIRECT_GENERIC("set_split_file_size", "system.file.split_size.set");
|
||||
CMD2_REDIRECT ("get_split_suffix", "system.file.split_suffix");
|
||||
CMD2_REDIRECT ("set_split_suffix", "system.file.split_suffix.set");
|
||||
CMD2_REDIRECT_GENERIC("set_split_suffix", "system.file.split_suffix.set");
|
||||
|
||||
CMD2_REDIRECT ("get_timeout_sync", "pieces.sync.timeout");
|
||||
CMD2_REDIRECT ("set_timeout_sync", "pieces.sync.timeout.set");
|
||||
CMD2_REDIRECT_GENERIC("set_timeout_sync", "pieces.sync.timeout.set");
|
||||
CMD2_REDIRECT ("get_timeout_safe_sync", "pieces.sync.timeout_safe");
|
||||
CMD2_REDIRECT ("set_timeout_safe_sync", "pieces.sync.timeout_safe.set");
|
||||
CMD2_REDIRECT_GENERIC("set_timeout_safe_sync", "pieces.sync.timeout_safe.set");
|
||||
|
||||
CMD2_REDIRECT_GENERIC("get_preload_type", "pieces.preload.type");
|
||||
CMD2_REDIRECT_GENERIC("get_preload_min_size", "pieces.preload.min_size");
|
||||
@@ -378,77 +369,77 @@ main(int argc, char** argv) {
|
||||
CMD2_REDIRECT_GENERIC("set_max_memory_usage", "pieces.memory.max.set");
|
||||
|
||||
CMD2_REDIRECT ("get_send_buffer_size", "network.send_buffer.size");
|
||||
CMD2_REDIRECT ("set_send_buffer_size", "network.send_buffer.size.set");
|
||||
CMD2_REDIRECT_GENERIC("set_send_buffer_size", "network.send_buffer.size.set");
|
||||
CMD2_REDIRECT ("get_receive_buffer_size", "network.receive_buffer.size");
|
||||
CMD2_REDIRECT ("set_receive_buffer_size", "network.receive_buffer.size.set");
|
||||
CMD2_REDIRECT_GENERIC("set_receive_buffer_size", "network.receive_buffer.size.set");
|
||||
|
||||
CMD2_REDIRECT ("get_up_rate", "throttle.global_up.rate");
|
||||
CMD2_REDIRECT ("get_up_total", "throttle.global_up.total");
|
||||
CMD2_REDIRECT ("get_upload_rate", "throttle.global_up.max_rate");
|
||||
CMD2_REDIRECT ("set_upload_rate", "throttle.global_up.max_rate.set");
|
||||
CMD2_REDIRECT_GENERIC("set_upload_rate", "throttle.global_up.max_rate.set");
|
||||
CMD2_REDIRECT ("get_down_rate", "throttle.global_down.rate");
|
||||
CMD2_REDIRECT ("get_down_total", "throttle.global_down.total");
|
||||
CMD2_REDIRECT ("get_download_rate", "throttle.global_down.max_rate");
|
||||
CMD2_REDIRECT ("set_download_rate", "throttle.global_down.max_rate.set");
|
||||
CMD2_REDIRECT_GENERIC("set_download_rate", "throttle.global_down.max_rate.set");
|
||||
|
||||
CMD2_REDIRECT ("bind", "network.bind_address.set");
|
||||
CMD2_REDIRECT ("set_bind", "network.bind_address.set");
|
||||
CMD2_REDIRECT_GENERIC("set_bind", "network.bind_address.set");
|
||||
CMD2_REDIRECT ("get_bind", "network.bind_address");
|
||||
|
||||
CMD2_REDIRECT ("ip", "network.local_address.set");
|
||||
CMD2_REDIRECT ("set_ip", "network.local_address.set");
|
||||
CMD2_REDIRECT_GENERIC("set_ip", "network.local_address.set");
|
||||
CMD2_REDIRECT ("get_ip", "network.local_address");
|
||||
|
||||
CMD2_REDIRECT ("port_range", "network.port_range.set");
|
||||
CMD2_REDIRECT ("get_port_range", "network.port_range");
|
||||
CMD2_REDIRECT ("set_port_range", "network.port_range.set");
|
||||
CMD2_REDIRECT_GENERIC("set_port_range", "network.port_range.set");
|
||||
|
||||
CMD2_REDIRECT ("port_random", "network.port_random.set");
|
||||
CMD2_REDIRECT ("get_port_random", "network.port_random");
|
||||
CMD2_REDIRECT ("set_port_random", "network.port_random.set");
|
||||
CMD2_REDIRECT_GENERIC("set_port_random", "network.port_random.set");
|
||||
|
||||
CMD2_REDIRECT ("port_open", "network.port_open.set");
|
||||
CMD2_REDIRECT ("get_port_open", "network.port_open");
|
||||
CMD2_REDIRECT ("set_port_open", "network.port_open.set");
|
||||
CMD2_REDIRECT_GENERIC("set_port_open", "network.port_open.set");
|
||||
|
||||
CMD2_REDIRECT ("proxy_address", "network.proxy_address.set");
|
||||
CMD2_REDIRECT ("set_proxy_address", "network.proxy_address.set");
|
||||
CMD2_REDIRECT_GENERIC("set_proxy_address", "network.proxy_address.set");
|
||||
CMD2_REDIRECT ("get_proxy_address", "network.proxy_address");
|
||||
|
||||
CMD2_REDIRECT ("scgi_port", "network.scgi.open_port");
|
||||
CMD2_REDIRECT ("scgi_local", "network.scgi.open_local");
|
||||
|
||||
CMD2_REDIRECT ("scgi_dont_route", "network.scgi.dont_route.set");
|
||||
CMD2_REDIRECT ("set_scgi_dont_route", "network.scgi.dont_route.set");
|
||||
CMD2_REDIRECT_GENERIC("set_scgi_dont_route", "network.scgi.dont_route.set");
|
||||
CMD2_REDIRECT ("get_scgi_dont_route", "network.scgi.dont_route");
|
||||
|
||||
CMD2_REDIRECT ("xmlrpc_dialect", "network.xmlrpc.size_limit.set");
|
||||
|
||||
CMD2_REDIRECT ("get_connection_leech", "connection_leech");
|
||||
CMD2_REDIRECT ("set_connection_leech", "connection_leech.set");
|
||||
CMD2_REDIRECT_GENERIC("set_connection_leech", "connection_leech.set");
|
||||
CMD2_REDIRECT ("get_connection_seed", "connection_seed");
|
||||
CMD2_REDIRECT ("set_connection_seed", "connection_seed.set");
|
||||
CMD2_REDIRECT_GENERIC("set_connection_seed", "connection_seed.set");
|
||||
|
||||
CMD2_REDIRECT ("peer_exchange", "protocol.pex.set");
|
||||
CMD2_REDIRECT ("get_peer_exchange", "protocol.pex");
|
||||
CMD2_REDIRECT ("set_peer_exchange", "protocol.pex.set");
|
||||
CMD2_REDIRECT_GENERIC("set_peer_exchange", "protocol.pex.set");
|
||||
|
||||
CMD2_REDIRECT ("dht", "dht.mode.set");
|
||||
CMD2_REDIRECT ("dht_add_node", "dht.add_node");
|
||||
CMD2_REDIRECT ("dht_statistics", "dht.statistics");
|
||||
CMD2_REDIRECT ("get_dht_port", "dht.port");
|
||||
CMD2_REDIRECT ("set_dht_port", "dht.port");
|
||||
CMD2_REDIRECT_GENERIC("set_dht_port", "dht.port");
|
||||
CMD2_REDIRECT ("get_dht_throttle", "dht.throttle.name");
|
||||
CMD2_REDIRECT ("set_dht_throttle", "dht.throttle.name.set");
|
||||
CMD2_REDIRECT_GENERIC("set_dht_throttle", "dht.throttle.name.set");
|
||||
|
||||
CMD2_REDIRECT ("directory", "directory.default.set");
|
||||
CMD2_REDIRECT ("get_directory", "directory.default");
|
||||
CMD2_REDIRECT ("set_directory", "directory.default.set");
|
||||
CMD2_REDIRECT_GENERIC("set_directory", "directory.default.set");
|
||||
|
||||
CMD2_REDIRECT ("get_session_lock", "system.session.use_lock");
|
||||
CMD2_REDIRECT ("set_session_lock", "system.session.use_lock.set");
|
||||
CMD2_REDIRECT_GENERIC("set_session_lock", "system.session.use_lock.set");
|
||||
CMD2_REDIRECT ("get_session_on_completion", "system.session.on_completion");
|
||||
CMD2_REDIRECT ("set_session_on_completion", "system.session.on_completion.set");
|
||||
CMD2_REDIRECT_GENERIC("set_session_on_completion", "system.session.on_completion.set");
|
||||
|
||||
CMD2_REDIRECT ("check_hash", "pieces.hash.on_completion.set");
|
||||
|
||||
@@ -640,8 +631,8 @@ main(int argc, char** argv) {
|
||||
// Functions that might not get depracted as they are nice for
|
||||
// configuration files, and thus might do with just some
|
||||
// cleanup.
|
||||
CMD2_REDIRECT ("upload_rate", "throttle.global_up.max_rate.set");
|
||||
CMD2_REDIRECT ("download_rate", "throttle.global_down.max_rate.set");
|
||||
CMD2_REDIRECT_GENERIC("upload_rate", "throttle.global_up.max_rate.set_kb");
|
||||
CMD2_REDIRECT_GENERIC("download_rate", "throttle.global_down.max_rate.set_kb");
|
||||
}
|
||||
|
||||
if (OptionParser::has_flag('n', argc, argv))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -16,6 +16,8 @@ rtorrentTest_SOURCES = \
|
||||
rpc/command_map_test.h \
|
||||
rpc/command_slot_test.cc \
|
||||
rpc/command_slot_test.h \
|
||||
rpc/object_storage_test.cc \
|
||||
rpc/object_storage_test.h \
|
||||
main.cc
|
||||
|
||||
rtorrentTest_CXXFLAGS = $(CPPUNIT_CFLAGS)
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
#include "config.h"
|
||||
|
||||
#import "object_storage_test.h"
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(ObjectStorageTest);
|
||||
|
||||
#define ASSERT_CATCH_INPUT_ERROR(some_code) \
|
||||
try { some_code; CPPUNIT_ASSERT("torrent::input_error not caught" && false); } catch (torrent::input_error& e) { }
|
||||
|
||||
void
|
||||
ObjectStorageTest::test_basics() {
|
||||
rpc::object_storage::iterator itr;
|
||||
|
||||
CPPUNIT_ASSERT(m_storage.empty());
|
||||
|
||||
itr = m_storage.insert("test_1", torrent::Object("a"), rpc::object_storage::flag_generic_type);
|
||||
|
||||
CPPUNIT_ASSERT(itr != m_storage.end());
|
||||
CPPUNIT_ASSERT(&*itr != NULL);
|
||||
CPPUNIT_ASSERT(itr->first.size() == 6 && std::strcmp(itr->first.data(), "test_1") == 0);
|
||||
CPPUNIT_ASSERT(itr->second.object.is_string() && itr->second.object.as_string() == "a");
|
||||
|
||||
ASSERT_CATCH_INPUT_ERROR( { m_storage.insert("test_1", torrent::Object("a"), rpc::object_storage::flag_generic_type); } );
|
||||
|
||||
// Test erase.
|
||||
m_storage.erase(rpc::object_storage::key_type::from_c_str("test_1"));
|
||||
CPPUNIT_ASSERT(m_storage.empty());
|
||||
|
||||
// Test with no type flag.
|
||||
ASSERT_CATCH_INPUT_ERROR( { m_storage.insert("test_2", torrent::Object("b"), 0); } );
|
||||
ASSERT_CATCH_INPUT_ERROR( { m_storage.insert("test_3", torrent::Object("c"), ~rpc::object_storage::mask_type); } );
|
||||
|
||||
m_storage.clear();
|
||||
}
|
||||
|
||||
void
|
||||
ObjectStorageTest::test_conversions() {
|
||||
CPPUNIT_ASSERT(m_storage.insert("test_1", torrent::Object("a"), rpc::object_storage::flag_generic_type) != m_storage.end());
|
||||
CPPUNIT_ASSERT(m_storage.insert_string(std::string("test_2"), torrent::Object("a"), rpc::object_storage::flag_generic_type) != m_storage.end());
|
||||
|
||||
char raw_3[8] = "test_3\x1";
|
||||
torrent::raw_string raw_string_3(raw_3, 6);
|
||||
|
||||
CPPUNIT_ASSERT(m_storage.insert(raw_string_3, torrent::Object("a"), rpc::object_storage::flag_generic_type)->first == std::string("test_3"));
|
||||
m_storage.clear();
|
||||
}
|
||||
|
||||
void
|
||||
ObjectStorageTest::test_validate_keys() {
|
||||
torrent::raw_string raw_string_4("test_4\0foo", 10);
|
||||
|
||||
ASSERT_CATCH_INPUT_ERROR( { m_storage.insert(raw_string_4, torrent::Object("a"), rpc::object_storage::flag_generic_type); } );
|
||||
}
|
||||
|
||||
// And test many other bad/good string combos.
|
||||
|
||||
// Test for various conversions of fixed_key_type.
|
||||
|
||||
void
|
||||
ObjectStorageTest::test_access() {
|
||||
m_storage.insert("generic_1", torrent::Object("gen_a"), rpc::object_storage::flag_generic_type);
|
||||
m_storage.insert("value_1", int64_t(1), rpc::object_storage::flag_value_type);
|
||||
|
||||
CPPUNIT_ASSERT(m_storage.get_c_str("generic_1").as_string() == "gen_a");
|
||||
CPPUNIT_ASSERT(m_storage.set_c_str("generic_1", int64_t(1)).as_value() == 1);
|
||||
|
||||
// Test value from raw and normal, list, etc.
|
||||
CPPUNIT_ASSERT(m_storage.get_c_str("value_1").as_value() == 1);
|
||||
CPPUNIT_ASSERT(m_storage.set_c_str("value_1", int64_t(2)).as_value() == 2);
|
||||
CPPUNIT_ASSERT(m_storage.set_c_str("value_1", "123").as_value() == 123);
|
||||
CPPUNIT_ASSERT(m_storage.set_c_str("value_1", torrent::raw_string::from_c_str("321")).as_value() == 321);
|
||||
// CPPUNIT_ASSERT(m_storage.set_c_str("value_1", torrent::raw_bencode::from_c_str("i567e")).as_value() == 567);
|
||||
|
||||
ASSERT_CATCH_INPUT_ERROR( { m_storage.set_c_str("value_1", "e123"); } );
|
||||
|
||||
// Test string from raw and normal, list, etc.
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
#include "rpc/object_storage.h"
|
||||
|
||||
class ObjectStorageTest : public CppUnit::TestFixture {
|
||||
CPPUNIT_TEST_SUITE(ObjectStorageTest);
|
||||
CPPUNIT_TEST(test_basics);
|
||||
CPPUNIT_TEST(test_conversions);
|
||||
CPPUNIT_TEST(test_validate_keys);
|
||||
CPPUNIT_TEST(test_access);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
void setUp() { }
|
||||
void tearDown() {}
|
||||
|
||||
void test_basics();
|
||||
|
||||
void test_conversions();
|
||||
void test_validate_keys();
|
||||
|
||||
void test_access();
|
||||
|
||||
private:
|
||||
rpc::object_storage m_storage;
|
||||
};
|
||||
Reference in New Issue
Block a user