mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-10-09 07:39:21 +00:00
* 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:
@@ -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 \
|
||||
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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()) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user