* Fixed more redirected commands.

* Cleaned up the Command stack implementation.

* Added framework for object_storage class that will hold variables and user-defined command lists.


git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@1162 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
rakshasa
2010-04-11 14:19:27 +00:00
parent 856228da3d
commit 74bae32243
15 changed files with 276 additions and 140 deletions
+2
View File
@@ -19,6 +19,8 @@ libsub_rpc_a_SOURCES = \
command_new_slot.h \
exec_file.cc \
exec_file.h \
object_storage.cc \
object_storage.h \
parse.cc \
parse.h \
parse_commands.cc \
+1
View File
@@ -157,6 +157,7 @@ public:
static torrent::Object* stack_end() { return current_stack.end(); }
static torrent::Object* push_stack(const torrent::Object::list_type& args, stack_type* stack);
static torrent::Object* push_stack(const torrent::Object* first_arg, const torrent::Object* last_arg, stack_type* stack);
static void pop_stack(stack_type* stack, torrent::Object* last_stack);
protected:
+20 -94
View File
@@ -49,105 +49,39 @@ namespace rpc {
// Temp until it can be moved somewhere better...
const torrent::Object
command_function_call(const torrent::raw_string& cmd, target_type target, const torrent::Object& args) {
char* buffer[sizeof(torrent::Object) * Command::max_arguments];
torrent::Object* stack = (torrent::Object*)buffer;
torrent::Object* first = (torrent::Object*)buffer;
rpc::Command::stack_type stack;
torrent::Object* last_stack;
if (args.is_list()) {
// Do nothing for now.
for (torrent::Object::list_const_iterator itr = args.as_list().begin(), last = args.as_list().end();
itr != last && first != stack + Command::max_arguments;
itr++, first++) {
new (first) torrent::Object(*itr);
first->swap(*Command::argument(std::distance(stack, first)));
}
} else if (args.type() != torrent::Object::TYPE_NONE) {
new (first) torrent::Object(args);
(first++)->swap(*Command::argument(0));
}
if (args.is_list())
last_stack = rpc::Command::push_stack(args.as_list(), &stack);
else if (args.type() != torrent::Object::TYPE_NONE)
last_stack = rpc::Command::push_stack(&args, &args + 1, &stack);
else
last_stack = rpc::Command::push_stack(NULL, NULL, &stack);
try {
torrent::Object result = parse_command_multiple(target, cmd.begin(), cmd.end());
while (first-- != stack) {
first->swap(*Command::argument(std::distance(stack, first)));
first->~Object();
}
rpc::Command::pop_stack(&stack, last_stack);
return result;
} catch (torrent::bencode_error& e) {
while (first-- != stack) {
first->swap(*Command::argument(std::distance(stack, first)));
first->~Object();
}
throw e;
}
}
const torrent::Object
CommandFunction::call(Command* rawCommand, target_type target, const torrent::Object& args) {
char* buffer[sizeof(torrent::Object) * Command::max_arguments];
torrent::Object* stack = (torrent::Object*)buffer;
torrent::Object* first = (torrent::Object*)buffer;
if (args.is_list()) {
// Do nothing for now.
for (torrent::Object::list_const_iterator itr = args.as_list().begin(), last = args.as_list().end();
itr != last && first != stack + Command::max_arguments;
itr++, first++) {
new (first) torrent::Object(*itr);
first->swap(*argument(std::distance(stack, first)));
}
} else if (args.type() != torrent::Object::TYPE_NONE) {
new (first) torrent::Object(args);
(first++)->swap(*argument(0));
}
CommandFunction* command = reinterpret_cast<CommandFunction*>(rawCommand);
try {
torrent::Object result = parse_command_multiple(target, command->m_command.c_str(), command->m_command.c_str() + command->m_command.size());
while (first-- != stack) {
first->swap(*argument(std::distance(stack, first)));
first->~Object();
}
return result;
} catch (torrent::bencode_error& e) {
while (first-- != stack) {
first->swap(*Command::argument(std::distance(stack, first)));
first->~Object();
}
rpc::Command::pop_stack(&stack, last_stack);
throw e;
}
}
const torrent::Object
CommandFunctionList::call(Command* rawCommand, target_type target, const torrent::Object& args) {
char* buffer[sizeof(torrent::Object) * Command::max_arguments];
torrent::Object* stack = (torrent::Object*)buffer;
torrent::Object* first = (torrent::Object*)buffer;
rpc::Command::stack_type stack;
torrent::Object* last_stack;
if (args.is_list()) {
// Do nothing for now.
for (torrent::Object::list_const_iterator itr = args.as_list().begin(), last = args.as_list().end();
itr != last && first != stack + Command::max_arguments;
itr++, first++) {
new (first) torrent::Object(*itr);
first->swap(*argument(std::distance(stack, first)));
}
} else if (args.type() != torrent::Object::TYPE_NONE) {
new (first) torrent::Object(args);
(first++)->swap(*argument(0));
}
if (args.is_list())
last_stack = rpc::Command::push_stack(args.as_list(), &stack);
else if (args.type() != torrent::Object::TYPE_NONE)
last_stack = rpc::Command::push_stack(&args, &args + 1, &stack);
else
last_stack = rpc::Command::push_stack(NULL, NULL, &stack);
CommandFunctionList* command = reinterpret_cast<CommandFunctionList*>(rawCommand);
@@ -156,19 +90,11 @@ CommandFunctionList::call(Command* rawCommand, target_type target, const torrent
parse_command_multiple(target, itr->second.c_str(), itr->second.c_str() + itr->second.size());
} catch (torrent::bencode_error& e) {
while (first-- != stack) {
first->swap(*Command::argument(std::distance(stack, first)));
first->~Object();
}
rpc::Command::pop_stack(&stack, last_stack);
throw e;
}
while (first-- != stack) {
first->swap(*argument(std::distance(stack, first)));
first->~Object();
}
rpc::Command::pop_stack(&stack, last_stack);
return torrent::Object();
}
+5 -14
View File
@@ -47,20 +47,6 @@
namespace rpc {
class CommandFunction : public Command {
public:
CommandFunction(const std::string& cmd = std::string()) : m_command(cmd) {}
const std::string& command() const { return m_command; }
void set_command(const std::string& cmd) { m_command = cmd; }
static const torrent::Object call(Command* rawCommand, target_type target, const torrent::Object& args);
private:
// TODO: Replace with a delete-me flag and const char*.
std::string m_command;
};
class CommandFunctionList : public Command,
private std::vector<std::pair<std::string, std::string> > {
public:
@@ -86,6 +72,11 @@ public:
const torrent::Object
command_function_call(const torrent::raw_string& cmd, target_type target, const torrent::Object& args);
inline const torrent::Object
command_function_call_str(const std::string& cmd, target_type target, const torrent::Object& args) {
return command_function_call(torrent::raw_string::from_string(cmd), target, args);
}
}
#endif
+10 -4
View File
@@ -77,18 +77,24 @@ get_target_cast<torrent::File*>(target_type target, int type) {
}
inline torrent::Object*
Command::push_stack(const torrent::Object::list_type& args, stack_type* stack) {
Command::push_stack(const torrent::Object* first_arg, const torrent::Object* last_arg, stack_type* stack) {
unsigned int idx = 0;
for (torrent::Object::list_const_iterator itr = args.begin(), last = args.end();
itr != last && idx < Command::max_arguments; itr++, idx++) {
new (&(*stack)[idx]) torrent::Object(*itr);
while (first_arg != last_arg && idx < Command::max_arguments) {
new (&(*stack)[idx]) torrent::Object(*first_arg++);
(*stack)[idx].swap(*Command::argument(idx));
idx++;
}
return stack->begin() + idx;
}
inline torrent::Object*
Command::push_stack(const torrent::Object::list_type& args, stack_type* stack) {
return push_stack(args.data(), args.data() + args.size(), stack);
}
inline void
Command::pop_stack(stack_type* stack, torrent::Object* last_stack) {
while (last_stack-- != stack->begin()) {
+43
View File
@@ -0,0 +1,43 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include "object_storage.h"
namespace rpc {
}
+93
View File
@@ -0,0 +1,93 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2007, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
// The object_storage type is responsible for storing variables,
// commands, command lists and other types encoded in torrent::Object
// format.
#ifndef RTORRENT_RPC_OBJECT_STORAGE_H
#define RTORRENT_RPC_OBJECT_STORAGE_H
#include <cstring>
#include <tr1/unordered_set>
#include <torrent/object.h>
namespace rpc {
// The key size should be such that the value type size which includes
// the next-pointer.
struct object_storage_node_internal {
torrent::Object object;
char key[0];
};
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;
using base_type::iterator;
};
inline std::size_t
hash_object_storage_node::operator () (const object_storage_node& p) {
std::size_t result = 0;
const char* first = p.key;
while (*first != '\0')
result = (result * 131) + *first++;
return result;
}
}
#endif
+8 -1
View File
@@ -229,8 +229,15 @@ SCgiTask::receive_write(const char* buffer, uint32_t length) {
m_bufferSize = length + headerSize;
std::memcpy(m_buffer + headerSize, buffer, length);
event_write();
if (m_parent->log_fd() >= 0) {
// Clean up logging, this is just plain ugly...
// write(m_logFd, "\n---\n", sizeof("\n---\n"));
write(m_parent->log_fd(), m_buffer, m_bufferSize);
write(m_parent->log_fd(), "\n---\n", sizeof("\n---\n"));
}
event_write();
return true;
}