From 85018327889e56a1e9b4e5b1f6fd04f557fd0de2 Mon Sep 17 00:00:00 2001 From: rakshasa Date: Mon, 9 Apr 2007 21:09:53 +0000 Subject: [PATCH] * Bumped to 0.11.5/0.7.5. * Added "call.set_upload_rate", "call.get_upload_rate" and "call.get_directory" XMLRPC calls. git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@888 e378c898-3ddf-0310-93e7-cc216c733640 --- configure.ac | 4 +- src/option_handler_rules.cc | 2 + src/rpc/fast_cgi.cc | 7 +- src/rpc/fast_cgi.h | 6 +- src/rpc/xmlrpc.cc | 126 ++++++++++++++++++++++++++++++---- src/rpc/xmlrpc.h | 11 +++ src/utils/variable.h | 8 +-- src/utils/variable_generic.cc | 15 ++-- src/utils/variable_map.cc | 12 ++++ src/utils/variable_map.h | 5 ++ 10 files changed, 164 insertions(+), 32 deletions(-) diff --git a/configure.ac b/configure.ac index bcd63582..94602180 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT(rtorrent, 0.7.4, jaris@ifi.uio.no) +AC_INIT(rtorrent, 0.7.5, jaris@ifi.uio.no) AM_INIT_AUTOMAKE AM_CONFIG_HEADER(config.h) @@ -22,7 +22,7 @@ TORRENT_WITHOUT_NCURSESW() TORRENT_WITHOUT_STATVFS() TORRENT_WITHOUT_STATFS() -PKG_CHECK_MODULES(STUFF, sigc++-2.0 libcurl >= 7.12.0 libtorrent >= 0.11.3, +PKG_CHECK_MODULES(STUFF, sigc++-2.0 libcurl >= 7.12.0 libtorrent >= 0.11.5, CXXFLAGS="$CXXFLAGS $STUFF_CFLAGS"; LIBS="$LIBS $STUFF_LIBS") diff --git a/src/option_handler_rules.cc b/src/option_handler_rules.cc index 7e447e40..a1626366 100644 --- a/src/option_handler_rules.cc +++ b/src/option_handler_rules.cc @@ -312,6 +312,8 @@ apply_fast_cgi(const std::string& arg) { if (control->xmlrpc() == NULL) { control->set_xmlrpc(new rpc::XmlRpc); + control->xmlrpc()->set_slot_call_command_get(rak::mem_fn(control->variable(), &utils::VariableMap::call_command_get)); + control->xmlrpc()->set_slot_call_command_set(rak::mem_fn(control->variable(), &utils::VariableMap::call_command_set)); } control->set_fast_cgi(new rpc::FastCgi(arg)); diff --git a/src/rpc/fast_cgi.cc b/src/rpc/fast_cgi.cc index 86cd96c0..1c4e8335 100644 --- a/src/rpc/fast_cgi.cc +++ b/src/rpc/fast_cgi.cc @@ -43,15 +43,14 @@ #include #include #include -#include -#include #include "globals.h" #include "control.h" #include "core/manager.h" - #endif +#include + #include "fast_cgi.h" namespace rpc { @@ -174,7 +173,7 @@ void FastCgi::event_read() {} void FastCgi::event_write() {} void FastCgi::event_error() {} -void FastCgi::receive_write(const char* buffer, uint32_t length); +bool FastCgi::receive_write(const char* buffer, uint32_t length) { return false; } #endif diff --git a/src/rpc/fast_cgi.h b/src/rpc/fast_cgi.h index 8c39a835..115545a3 100644 --- a/src/rpc/fast_cgi.h +++ b/src/rpc/fast_cgi.h @@ -38,15 +38,11 @@ #define RTORRENT_RPC_FAST_CGI_H #include +#include #include struct FCGX_Request; -namespace rak { - template class function2; - template class function3; -} - namespace rpc { class FastCgi : public torrent::Event { diff --git a/src/rpc/xmlrpc.cc b/src/rpc/xmlrpc.cc index c0761f31..7ff559de 100644 --- a/src/rpc/xmlrpc.cc +++ b/src/rpc/xmlrpc.cc @@ -36,37 +36,128 @@ #include "config.h" +#ifdef HAVE_XMLRPC_C +#include #include #include +#endif + +#include +#include #include "xmlrpc.h" namespace rpc { -xmlrpc_value* -xmlrpc_test_add(xmlrpc_env* env, xmlrpc_value* value, void* serverInfo) { - // Grabbed from the XMLRPC-C examples. - xmlrpc_int32 x, y, z; +#ifdef HAVE_XMLRPC_C + +struct server_info_t { + server_info_t(const char* command, XmlRpc::slot_call_command* callCommand) : + m_command(command), m_callCommand(callCommand) {} + + const char* m_command; + XmlRpc::slot_call_command* m_callCommand; +}; + +xmlrpc_value* +xmlrpc_call_command(xmlrpc_env* env, xmlrpc_value* args, void* voidServerInfo) { + torrent::Object object(torrent::Object::TYPE_LIST); + torrent::Object::list_type& objectList = object.as_list(); + + if (xmlrpc_value_type(args) != XMLRPC_TYPE_ARRAY) + throw torrent::internal_error("xmlrpc_value_type(args) != XMLRPC_TYPE_ARRAY"); + + unsigned int last = xmlrpc_array_size(env, args); - /* Parse our argument array. */ - xmlrpc_parse_value(env, value, "(ii)", &x, &y); if (env->fault_occurred) return NULL; - /* Add our two numbers. */ - z = x + y; + for (unsigned int i = 0; i != last; i++) { + xmlrpc_value* value; + xmlrpc_array_read_item(env, args, i, &value); - /* Return our result. */ - return xmlrpc_build_value(env, "i", z); + if (env->fault_occurred) + return NULL; + + switch (xmlrpc_value_type(value)) { + case XMLRPC_TYPE_INT: + int v; + xmlrpc_read_int(env, value, &v); + + objectList.push_back(torrent::Object((int64_t)v)); + break; + +// case XMLRPC_TYPE_BOOL: +// case XMLRPC_TYPE_DOUBLE: +// case XMLRPC_TYPE_DATETIME: + + case XMLRPC_TYPE_STRING: + const char* valueString; + xmlrpc_read_string(env, value, &valueString); + + if (env->fault_occurred) + return NULL; + + objectList.push_back(torrent::Object(std::string(valueString))); + + // Urgh, seriously? + ::free((void*)valueString); + break; + +// case XMLRPC_TYPE_BASE64: +// case XMLRPC_TYPE_ARRAY: +// case XMLRPC_TYPE_STRUCT: +// case XMLRPC_TYPE_C_PTR: +// case XMLRPC_TYPE_NIL: +// case XMLRPC_TYPE_DEAD: + default: + xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Unsupported type found."); + return NULL; + } + + if (env->fault_occurred) + return NULL; + } + + try { + server_info_t* serverInfo = reinterpret_cast(voidServerInfo); + + const torrent::Object& resultObject = (*serverInfo->m_callCommand)(serverInfo->m_command, object); + + xmlrpc_value* result; + xmlrpc_int32 tmpInt; + + switch (resultObject.type()) { + case torrent::Object::TYPE_VALUE: + tmpInt = resultObject.as_value(); + result = xmlrpc_build_value(env, "i", tmpInt); + break; + + case torrent::Object::TYPE_STRING: + result = xmlrpc_string_new(env, resultObject.as_string().c_str()); + break; + + default: + tmpInt = 1; + result = xmlrpc_build_value(env, "i", tmpInt); + } + + return result; + + } catch (torrent::local_error& e) { + xmlrpc_env_set_fault(env, XMLRPC_PARSE_ERROR, e.what()); + return NULL; + } } XmlRpc::XmlRpc() : m_env(new xmlrpc_env) { xmlrpc_env_init(m_env); - m_registry = xmlrpc_registry_new(m_env); - // Move this out. - xmlrpc_registry_add_method_w_doc(m_env, m_registry, NULL, "my.test", &xmlrpc_test_add, new int, "i:ii", "Not much."); + xmlrpc_registry_add_method_w_doc(m_env, m_registry, NULL, "call.set_upload_rate", &xmlrpc_call_command, new server_info_t("upload_rate", &m_slotSet), "i:i", ""); + xmlrpc_registry_add_method_w_doc(m_env, m_registry, NULL, "call.get_upload_rate", &xmlrpc_call_command, new server_info_t("upload_rate", &m_slotGet), "i:", ""); + + xmlrpc_registry_add_method_w_doc(m_env, m_registry, NULL, "call.get_directory", &xmlrpc_call_command, new server_info_t("directory", &m_slotGet), "s:", ""); } XmlRpc::~XmlRpc() { @@ -90,4 +181,13 @@ XmlRpc::process(const char* inBuffer, uint32_t length, slot_write slotWrite) { return result; } +#else + +XmlRpc::XmlRpc() { throw torrent::resource_error("XMLRPC not supported."); } +XmlRpc::~XmlRpc() {} + +bool XmlRpc::process(const char* inBuffer, uint32_t length, slot_write slotWrite) { return false; } + +#endif + } diff --git a/src/rpc/xmlrpc.h b/src/rpc/xmlrpc.h index aab521ec..99cc99f6 100644 --- a/src/rpc/xmlrpc.h +++ b/src/rpc/xmlrpc.h @@ -42,20 +42,31 @@ typedef struct _xmlrpc_env xmlrpc_env; typedef struct _xmlrpc_registry xmlrpc_registry; +namespace torrent { + class Object; +} + namespace rpc { class XmlRpc { public: typedef rak::function2 slot_write; + typedef rak::function2 slot_call_command; XmlRpc(); ~XmlRpc(); bool process(const char* inBuffer, uint32_t length, slot_write slotWrite); + void set_slot_call_command_get(slot_call_command::base_type* s) { m_slotGet.set(s); } + void set_slot_call_command_set(slot_call_command::base_type* s) { m_slotSet.set(s); } + private: xmlrpc_env* m_env; xmlrpc_registry* m_registry; + + slot_call_command m_slotGet; + slot_call_command m_slotSet; }; } diff --git a/src/utils/variable.h b/src/utils/variable.h index e0f6b172..f717334d 100644 --- a/src/utils/variable.h +++ b/src/utils/variable.h @@ -66,13 +66,13 @@ public: static const char* string_to_value_unit(const char* pos, value_type* value, int base, int unit); static bool string_to_value_unit_nothrow(const char* pos, value_type* value, int base, int unit); -protected: - Variable(const Variable&); - void operator = (const Variable&); - // Temporary hack, until torrent::Object is extended to allow // references so we can return a copy, not a const reference. static const torrent::Object m_emptyObject; + +protected: + Variable(const Variable&); + void operator = (const Variable&); }; } diff --git a/src/utils/variable_generic.cc b/src/utils/variable_generic.cc index 4e554408..ec311511 100644 --- a/src/utils/variable_generic.cc +++ b/src/utils/variable_generic.cc @@ -172,15 +172,22 @@ VariableValueSlot::get() { } void -VariableValueSlot::set(const torrent::Object& arg) { +VariableValueSlot::set(const torrent::Object& rawArg) { if (!m_slotSet.is_valid()) return; + const torrent::Object* arg; + + if (rawArg.type() == torrent::Object::TYPE_LIST && rawArg.as_list().size() == 1) + arg = &rawArg.as_list().front(); + else + arg = &rawArg; + value_type value; - switch (arg.type()) { + switch (arg->type()) { case torrent::Object::TYPE_STRING: - string_to_value_unit(arg.as_string().c_str(), &value, m_base, m_unit); + string_to_value_unit(arg->as_string().c_str(), &value, m_base, m_unit); // Check if we hit the end of the input. @@ -188,7 +195,7 @@ VariableValueSlot::set(const torrent::Object& arg) { break; case torrent::Object::TYPE_VALUE: - m_slotSet(arg.as_value()); + m_slotSet(arg->as_value()); break; default: diff --git a/src/utils/variable_map.cc b/src/utils/variable_map.cc index e518aeaf..b1fd4c37 100644 --- a/src/utils/variable_map.cc +++ b/src/utils/variable_map.cc @@ -236,4 +236,16 @@ VariableMap::process_file(key_type path) { return true; } +const VariableMap::mapped_type& +VariableMap::call_command_get(key_type key, const mapped_type& arg) { + return get(key); +} + +const VariableMap::mapped_type& +VariableMap::call_command_set(key_type key, const mapped_type& arg) { + set(key, arg); + + return Variable::m_emptyObject; +} + } diff --git a/src/utils/variable_map.h b/src/utils/variable_map.h index 085bfcfa..ad6954c7 100644 --- a/src/utils/variable_map.h +++ b/src/utils/variable_map.h @@ -117,6 +117,11 @@ public: void process_stream(std::istream* str); bool process_file(key_type path); + // The new API, which is atm just a wrapper over the old and + // requires seperate calls to get and set. These will be merged. + const mapped_type& call_command_get(key_type key, const mapped_type& arg); + const mapped_type& call_command_set(key_type key, const mapped_type& arg); + private: VariableMap(const VariableMap&); void operator = (const VariableMap&);