diff --git a/src/Makefile.am b/src/Makefile.am index 3560a343..65b8871e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,11 +18,10 @@ rtorrent_LDADD = \ rtorrent_SOURCES = \ command_events.cc \ - command_events.h \ command_helpers.cc \ command_helpers.h \ + command_network.cc \ command_ui.cc \ - command_ui.h \ command_scheduler.cc \ command_scheduler.h \ command_scheduler_item.cc \ diff --git a/src/command_events.cc b/src/command_events.cc index a8ce8187..653b0925 100644 --- a/src/command_events.cc +++ b/src/command_events.cc @@ -36,6 +36,9 @@ #include "config.h" +#include +#include +#include #include #include @@ -49,7 +52,7 @@ #include "control.h" #include "command_helpers.h" -void +torrent::Object apply_on_state_change(core::DownloadList::slot_map* slotMap, const torrent::Object& rawArgs) { const torrent::Object::list_type& args = rawArgs.as_list(); @@ -66,9 +69,11 @@ apply_on_state_change(core::DownloadList::slot_map* slotMap, const torrent::Obje else (*slotMap)[key] = sigc::bind(sigc::mem_fun(control->download_variables(), &utils::VariableMap::process_d_std_single), utils::convert_list_to_command(++args.begin(), args.end())); + + return torrent::Object(); } -void +torrent::Object apply_stop_on_ratio(const torrent::Object& rawArgs) { const torrent::Object::list_type& args = rawArgs.as_list(); @@ -100,6 +105,68 @@ apply_stop_on_ratio(const torrent::Object& rawArgs) { ++itr; } + + return torrent::Object(); +} + +torrent::Object +apply_start_tied() { + for (core::DownloadList::iterator itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ++itr) { + if ((*itr)->get_value("state") == 1) + continue; + + rak::file_stat fs; + const std::string& tiedToFile = (*itr)->get_string("tied_to_file"); + + if (!tiedToFile.empty() && fs.update(rak::path_expand(tiedToFile))) + control->core()->download_list()->start_try(*itr); + } + + return torrent::Object(); +} + +torrent::Object +apply_stop_untied() { + for (core::DownloadList::iterator itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ++itr) { + if ((*itr)->get_value("state") == 0) + continue; + + rak::file_stat fs; + const std::string& tiedToFile = (*itr)->get_string("tied_to_file"); + + if (!tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile))) + control->core()->download_list()->stop_try(*itr); + } + + return torrent::Object(); +} + +torrent::Object +apply_close_untied() { + for (core::DownloadList::iterator itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ++itr) { + rak::file_stat fs; + const std::string& tiedToFile = (*itr)->get_string("tied_to_file"); + + if (!tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile)) && control->core()->download_list()->stop_try(*itr)) + control->core()->download_list()->close(*itr); + } + + return torrent::Object(); +} + +torrent::Object +apply_remove_untied() { + for (core::DownloadList::iterator itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ) { + rak::file_stat fs; + const std::string& tiedToFile = (*itr)->get_string("tied_to_file"); + + if (!tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile)) && control->core()->download_list()->stop_try(*itr)) + itr = control->core()->download_list()->erase(itr); + else + ++itr; + } + + return torrent::Object(); } void @@ -119,4 +186,9 @@ initialize_command_events() { ADD_COMMAND_SLOT("on_finished", call_list, rak::bind_ptr_fn(&apply_on_state_change, &downloadList->slot_map_finished())); ADD_COMMAND_SLOT("stop_on_ratio", call_list, rak::ptr_fn(&apply_stop_on_ratio)); + + ADD_COMMAND_SLOT("start_tied", call_string, utils::object_fn(&apply_start_tied)); + ADD_COMMAND_SLOT("stop_untied", call_string, utils::object_fn(&apply_stop_untied)); + ADD_COMMAND_SLOT("close_untied", call_string, utils::object_fn(&apply_close_untied)); + ADD_COMMAND_SLOT("remove_untied", call_string, utils::object_fn(&apply_remove_untied)); } diff --git a/src/command_helpers.cc b/src/command_helpers.cc index dceaa443..e35a620e 100644 --- a/src/command_helpers.cc +++ b/src/command_helpers.cc @@ -55,6 +55,7 @@ initialize_commands() { initialize_variables(); initialize_download_variables(); initialize_command_events(); + initialize_command_network(); initialize_command_ui(); if (commandSlotsItr != commandSlots + COMMAND_SLOTS_SIZE || diff --git a/src/command_helpers.h b/src/command_helpers.h index ef81ee6b..a3d7e3db 100644 --- a/src/command_helpers.h +++ b/src/command_helpers.h @@ -46,8 +46,8 @@ namespace utils { // By using a static array we avoid allocating the variables on the // heap. This should reduce memory use and improve cache locality. -#define COMMAND_SLOTS_SIZE 18 -#define COMMAND_VARIABLES_SIZE 23 +#define COMMAND_SLOTS_SIZE 24 +#define COMMAND_VARIABLES_SIZE 24 extern utils::CommandSlot commandSlots[COMMAND_SLOTS_SIZE]; extern utils::CommandSlot* commandSlotsItr; @@ -57,6 +57,7 @@ extern utils::CommandVariable* commandVariablesItr; void initialize_variables(); void initialize_download_variables(); void initialize_command_events(); +void initialize_command_network(); void initialize_command_ui(); void initialize_commands(); diff --git a/src/command_network.cc b/src/command_network.cc new file mode 100644 index 00000000..45f10403 --- /dev/null +++ b/src/command_network.cc @@ -0,0 +1,113 @@ +// rTorrent - BitTorrent client +// Copyright (C) 2005-2006, 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 +// +// Skomakerveien 33 +// 3185 Skoppum, NORWAY + +#include "config.h" + +#include +#include +#include +#include + +#include "core/download_list.h" +#include "core/manager.h" +#include "utils/command_slot.h" +#include "utils/command_variable.h" +#include "utils/variable_map.h" + +#include "globals.h" +#include "control.h" +#include "command_helpers.h" + +torrent::Object +apply_encryption(const torrent::Object& rawArgs) { + const torrent::Object::list_type& args = rawArgs.as_list(); + + uint32_t options_mask = torrent::ConnectionManager::encryption_none; + + for (torrent::Object::list_type::const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) { + const std::string& opt = itr->as_string(); + + if (opt == "none") + options_mask = torrent::ConnectionManager::encryption_none; + else if (opt == "allow_incoming") + options_mask |= torrent::ConnectionManager::encryption_allow_incoming; + else if (opt == "try_outgoing") + options_mask |= torrent::ConnectionManager::encryption_try_outgoing; + else if (opt == "require") + options_mask |= torrent::ConnectionManager::encryption_require; + else if (opt == "require_RC4" || opt == "require_rc4") + options_mask |= torrent::ConnectionManager::encryption_require_RC4; + else if (opt == "enable_retry") + options_mask |= torrent::ConnectionManager::encryption_enable_retry; + else if (opt == "prefer_plaintext") + options_mask |= torrent::ConnectionManager::encryption_prefer_plaintext; + else + throw torrent::input_error("Invalid encryption option '" + opt + "'."); + } + + torrent::connection_manager()->set_encryption_options(options_mask); + + return torrent::Object(); +} + +void +initialize_command_network() { + utils::VariableMap* variables = control->variable(); +// core::DownloadList* downloadList = control->core()->download_list(); + + ADD_VARIABLE_BOOL("use_udp_trackers", true); + + ADD_VARIABLE_BOOL("port_open", true); + ADD_VARIABLE_BOOL("port_random", true); + ADD_VARIABLE_STRING("port_range", "6890-6999"); + + ADD_VARIABLE_STRING("connection_leech", "leech"); + ADD_VARIABLE_STRING("connection_seed", "seed"); + + ADD_VARIABLE_VALUE("min_peers", 40); + ADD_VARIABLE_VALUE("max_peers", 100); + ADD_VARIABLE_VALUE("min_peers_seed", -1); + ADD_VARIABLE_VALUE("max_peers_seed", -1); + + ADD_VARIABLE_VALUE("max_uploads", 15); + ADD_VARIABLE_VALUE("max_uploads_div", 1); + + ADD_VARIABLE_VALUE("max_downloads_div", 0); + + ADD_VARIABLE_VALUE("tracker_numwant", -1); + + ADD_COMMAND_SLOT("encryption", call_list, rak::ptr_fn(&apply_encryption)); +} diff --git a/src/command_ui.cc b/src/command_ui.cc index 53e5ce02..fc231567 100644 --- a/src/command_ui.cc +++ b/src/command_ui.cc @@ -36,6 +36,7 @@ #include "config.h" +#include #include #include @@ -43,6 +44,7 @@ #include "core/manager.h" #include "core/view_manager.h" #include "utils/command_slot.h" +#include "utils/command_variable.h" #include "utils/parse.h" #include "globals.h" @@ -51,7 +53,7 @@ typedef void (core::ViewManager::*view_filter_slot)(const std::string&, const core::ViewManager::sort_args&); -void +torrent::Object apply_view_filter(view_filter_slot viewFilterSlot, const torrent::Object& rawArgs) { const torrent::Object::list_type& args = rawArgs.as_list(); @@ -69,9 +71,11 @@ apply_view_filter(view_filter_slot viewFilterSlot, const torrent::Object& rawArg filterArgs.push_back(itr->as_string()); (control->view_manager()->*viewFilterSlot)(name, filterArgs); + + return torrent::Object(); } -void +torrent::Object apply_view_sort(const torrent::Object& rawArgs) { const torrent::Object::list_type& args = rawArgs.as_list(); @@ -89,6 +93,8 @@ apply_view_sort(const torrent::Object& rawArgs) { value = utils::convert_to_value(args.back()); control->view_manager()->sort(name, value); + + return torrent::Object(); } void @@ -96,10 +102,18 @@ initialize_command_ui() { utils::VariableMap* variables = control->variable(); // core::DownloadList* downloadList = control->core()->download_list(); + ADD_VARIABLE_STRING("key_layout", "qwerty"); + + ADD_COMMAND_SLOT("view_add", call_string, utils::object_string_fn(rak::make_mem_fun(control->view_manager(), &core::ViewManager::insert_throw))); + ADD_COMMAND_SLOT("view_filter", call_list, rak::bind_ptr_fn(&apply_view_filter, &core::ViewManager::set_filter)); ADD_COMMAND_SLOT("view_filter_on", call_list, rak::bind_ptr_fn(&apply_view_filter, &core::ViewManager::set_filter_on)); ADD_COMMAND_SLOT("view_sort", call_list, rak::ptr_fn(&apply_view_sort)); ADD_COMMAND_SLOT("view_sort_new", call_list, rak::bind_ptr_fn(&apply_view_filter, &core::ViewManager::set_sort_new)); ADD_COMMAND_SLOT("view_sort_current", call_list, rak::bind_ptr_fn(&apply_view_filter, &core::ViewManager::set_sort_current)); + +// ADD_COMMAND_SLOT("view_sort_current", call_list, rak::bind_ptr_fn(&apply_view_filter, &core::ViewManager::set_sort_current)); + + ADD_COMMAND_SLOT("print", call_string, utils::object_string_fn(rak::make_mem_fun(control->core(), &core::Manager::push_log))); } diff --git a/src/core/download.cc b/src/core/download.cc index 6ba8f1f3..526600f3 100644 --- a/src/core/download.cc +++ b/src/core/download.cc @@ -207,9 +207,9 @@ Download::receive_chunk_failed(__UNUSED uint32_t idx) { } int64_t Download::get_value(const char* key) { return control->download_variables()->get_d_value(this, key); } -const std::string& Download::get_string(const char* key) { return control->download_variables()->get_d_string(this, key); } +const std::string Download::get_string(const char* key) { return control->download_variables()->get_d_string(this, key); } int64_t Download::get_std_value(const std::string& key) { return control->download_variables()->get_d_value(this, key.c_str()); } -const std::string& Download::get_std_string(const std::string& key) { return control->download_variables()->get_d_string(this, key.c_str()); } +const std::string Download::get_std_string(const std::string& key) { return control->download_variables()->get_d_string(this, key.c_str()); } void Download::set(const char* key, const torrent::Object& value) { return control->download_variables()->set_d(this, key, value); } void Download::set_value(const char* key, int64_t value) { return control->download_variables()->set_d_value(this, key, value); } void Download::set_string(const char* key, const std::string& value) { return control->download_variables()->set_d_string(this, key, value); } diff --git a/src/core/download.h b/src/core/download.h index adacfc85..85d660cc 100644 --- a/src/core/download.h +++ b/src/core/download.h @@ -101,10 +101,10 @@ public: void set_priority(uint32_t p); int64_t get_value(const char* key); - const std::string& get_string(const char* key); + const std::string get_string(const char* key); int64_t get_std_value(const std::string& key); - const std::string& get_std_string(const std::string& key); + const std::string get_std_string(const std::string& key); void set(const char* key, const torrent::Object& value); diff --git a/src/core/manager.cc b/src/core/manager.cc index b97371b6..0bab4d65 100644 --- a/src/core/manager.cc +++ b/src/core/manager.cc @@ -184,9 +184,7 @@ Manager::delete_tied(Download* download) { Manager::Manager() : m_hashingView(NULL), - m_pollManager(NULL), - m_portFirst(6890), - m_portLast(6999) { + m_pollManager(NULL) { m_downloadStore = new DownloadStore(); m_downloadList = new DownloadList(); @@ -276,25 +274,40 @@ Manager::shutdown(bool force) { void Manager::listen_open() { + // This stuff really should be moved outside of manager, make it + // part of the init script. if (!control->variable()->get_value("get_port_open")) return; - if (m_portFirst > m_portLast) - throw torrent::input_error("Invalid port range for listening"); + int portFirst, portLast; + torrent::Object portRange = control->variable()->get("get_port_range"); + + if (portRange.is_string()) { + if (std::sscanf(portRange.as_string().c_str(), "%i-%i", &portFirst, &portLast) != 2) + throw torrent::input_error("Invalid port_range argument."); + +// } else if (portRange.is_list()) { + + } else { + throw torrent::input_error("Invalid port_range argument."); + } + + if (portFirst > portLast || portLast >= (1 << 16)) + throw torrent::input_error("Invalid port range."); if (control->variable()->get_value("get_port_random")) { - int boundary = m_portFirst + random() % (m_portLast - m_portFirst + 1); + int boundary = portFirst + random() % (portLast - portFirst + 1); - if (torrent::connection_manager()->listen_open(boundary, m_portLast) || - torrent::connection_manager()->listen_open(m_portFirst, boundary)) + if (torrent::connection_manager()->listen_open(boundary, portLast) || + torrent::connection_manager()->listen_open(portFirst, boundary)) return; } else { - if (torrent::connection_manager()->listen_open(m_portFirst, m_portLast)) + if (torrent::connection_manager()->listen_open(portFirst, portLast)) return; } - throw torrent::input_error("Could not open/bind a port for listening: " + std::string(rak::error_number::current().c_str())); + throw torrent::input_error("Could not open/bind port for listening: " + std::string(rak::error_number::current().c_str())); } std::string diff --git a/src/core/manager.h b/src/core/manager.h index 6db374b4..043e3dd2 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -74,8 +74,6 @@ public: Log& get_log_important() { return m_logImportant; } Log& get_log_complete() { return m_logComplete; } - void set_port_range(int a, int b) { m_portFirst = a; m_portLast = b; } - // Really should find a more descriptive name. void initialize_first(); void initialize_second(); @@ -123,9 +121,6 @@ private: PollManager* m_pollManager; Log m_logImportant; Log m_logComplete; - - int m_portFirst; - int m_portLast; }; } diff --git a/src/option_handler_rules.cc b/src/option_handler_rules.cc index 239ac799..08e44c58 100644 --- a/src/option_handler_rules.cc +++ b/src/option_handler_rules.cc @@ -99,74 +99,11 @@ namespace core { void apply_hash_read_ahead(int arg) { torrent::set_hash_read_ahead(arg << 20); } void apply_hash_interval(int arg) { torrent::set_hash_interval(arg * 1000); } -// The arg string *must* have been checked with validate_port_range -// first. -void -apply_port_range(const std::string& arg) { - int a = 0, b = 0; - - std::sscanf(arg.c_str(), "%i-%i", &a, &b); - - control->core()->set_port_range(a, b); -} - void apply_load(const std::string& arg) { control->core()->try_create_download_expand(arg, false, false, true); } void apply_load_verbose(const std::string& arg) { control->core()->try_create_download_expand(arg, false, true, true); } void apply_load_start(const std::string& arg) { control->core()->try_create_download_expand(arg, true, false, true); } void apply_load_start_verbose(const std::string& arg) { control->core()->try_create_download_expand(arg, true, true, true); } -void -apply_start_tied() { - for (core::DownloadList::iterator itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ++itr) { - if ((*itr)->get_value("state") == 1) - continue; - - rak::file_stat fs; - const std::string& tiedToFile = (*itr)->get_string("tied_to_file"); - - if (!tiedToFile.empty() && fs.update(rak::path_expand(tiedToFile))) - control->core()->download_list()->start_try(*itr); - } -} - -void -apply_stop_untied() { - for (core::DownloadList::iterator itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ++itr) { - if ((*itr)->get_value("state") == 0) - continue; - - rak::file_stat fs; - const std::string& tiedToFile = (*itr)->get_string("tied_to_file"); - - if (!tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile))) - control->core()->download_list()->stop_try(*itr); - } -} - -void -apply_close_untied() { - for (core::DownloadList::iterator itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ++itr) { - rak::file_stat fs; - const std::string& tiedToFile = (*itr)->get_string("tied_to_file"); - - if (!tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile)) && control->core()->download_list()->stop_try(*itr)) - control->core()->download_list()->close(*itr); - } -} - -void -apply_remove_untied() { - for (core::DownloadList::iterator itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ) { - rak::file_stat fs; - const std::string& tiedToFile = (*itr)->get_string("tied_to_file"); - - if (!tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile)) && control->core()->download_list()->stop_try(*itr)) - itr = control->core()->download_list()->erase(itr); - else - ++itr; - } -} - void apply_close_low_diskspace(int64_t arg) { core::Manager::DListItr itr = control->core()->download_list()->begin(); @@ -188,36 +125,6 @@ apply_encoding_list(const std::string& arg) { torrent::encoding_list()->push_back(arg); } -void -apply_encryption(const torrent::Object& rawArgs) { - const torrent::Object::list_type& args = rawArgs.as_list(); - - uint32_t options_mask = torrent::ConnectionManager::encryption_none; - - for (torrent::Object::list_type::const_iterator itr = args.begin(), last = args.end(); itr != last; itr++) { - const std::string& opt = itr->as_string(); - - if (opt == "none") - options_mask = torrent::ConnectionManager::encryption_none; - else if (opt == "allow_incoming") - options_mask |= torrent::ConnectionManager::encryption_allow_incoming; - else if (opt == "try_outgoing") - options_mask |= torrent::ConnectionManager::encryption_try_outgoing; - else if (opt == "require") - options_mask |= torrent::ConnectionManager::encryption_require; - else if (opt == "require_RC4" || opt == "require_rc4") - options_mask |= torrent::ConnectionManager::encryption_require_RC4; - else if (opt == "enable_retry") - options_mask |= torrent::ConnectionManager::encryption_enable_retry; - else if (opt == "prefer_plaintext") - options_mask |= torrent::ConnectionManager::encryption_prefer_plaintext; - else - throw torrent::input_error("Invalid encryption option '" + opt + "'."); - } - - torrent::connection_manager()->set_encryption_options(options_mask); -} - void apply_enable_trackers(const std::string& arg) { bool state = (arg != "no"); @@ -290,7 +197,7 @@ apply_try_import(const std::string& path) { control->core()->push_log("Could not read resource file: " + path); } -void +torrent::Object apply_schedule(const torrent::Object& rawArgs) { const torrent::Object::list_type& args = rawArgs.as_list(); @@ -304,6 +211,8 @@ apply_schedule(const torrent::Object& rawArgs) { const std::string& arg3 = (itr++)->as_string(); control->command_scheduler()->parse(arg1, arg2, arg3, utils::convert_list_to_command(itr, args.end())); + + return torrent::Object(); } void @@ -311,9 +220,7 @@ initialize_variables() { utils::VariableMap* variables = control->variable(); ADD_VARIABLE_BOOL("check_hash", true); - ADD_VARIABLE_BOOL("use_udp_trackers", true); - ADD_VARIABLE_BOOL("port_open", true); - ADD_VARIABLE_BOOL("port_random", true); + ADD_VARIABLE_BOOL("handshake_log", false); ADD_VARIABLE_BOOL("session_lock", true); ADD_VARIABLE_BOOL("session_on_completion", true); @@ -324,9 +231,6 @@ initialize_variables() { rak::mem_fn(control->core()->download_store(), &core::DownloadStore::set_path))); variables->insert("session_save", new utils::VariableVoidSlot(rak::mem_fn(control->core()->download_list(), &core::DownloadList::session_save))); - ADD_VARIABLE_STRING("connection_leech", "leech"); - ADD_VARIABLE_STRING("connection_seed", "seed"); - ADD_VARIABLE_STRING("directory", "./"); variables->insert("tos", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_tos))); @@ -343,16 +247,8 @@ initialize_variables() { variables->insert("fast_cgi", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_fast_cgi))); // ADD_VARIABLE_VALUE("max_chunks_queued", 0); - ADD_VARIABLE_VALUE("min_peers", 40); - ADD_VARIABLE_VALUE("max_peers", 100); - ADD_VARIABLE_VALUE("min_peers_seed", -1); - ADD_VARIABLE_VALUE("max_peers_seed", -1); - - ADD_VARIABLE_VALUE("max_uploads", 15); - ADD_VARIABLE_VALUE("max_uploads_div", 1); variables->insert("max_uploads_global", new utils::VariableValueSlot(rak::mem_fn(control->ui(), &ui::Root::max_uploads_global), rak::mem_fn(control->ui(), &ui::Root::set_max_uploads_global))); - ADD_VARIABLE_VALUE("max_downloads_div", 0); variables->insert("max_downloads_global", new utils::VariableValueSlot(rak::mem_fn(control->ui(), &ui::Root::max_downloads_global), rak::mem_fn(control->ui(), &ui::Root::set_max_downloads_global))); @@ -361,8 +257,6 @@ initialize_variables() { variables->insert("upload_rate", new utils::VariableValueSlot(rak::ptr_fn(&torrent::up_throttle), rak::mem_fn(control->ui(), &ui::Root::set_up_throttle_i64), 0, (1 << 10))); - ADD_VARIABLE_VALUE("tracker_numwant", -1); - variables->insert("hash_max_tries", new utils::VariableValueSlot(rak::ptr_fn(&torrent::hash_max_tries), rak::ptr_fn(&torrent::set_hash_max_tries))); variables->insert("max_open_files", new utils::VariableValueSlot(rak::ptr_fn(&torrent::max_open_files), rak::ptr_fn(&torrent::set_max_open_files))); variables->insert("max_open_sockets", new utils::VariableValueSlot(rak::mem_fn(torrent::connection_manager(), &torrent::ConnectionManager::max_size), @@ -410,8 +304,6 @@ initialize_variables() { ADD_VARIABLE_VALUE("split_file_size", -1); ADD_VARIABLE_STRING("split_suffix", ".part"); - variables->insert("port_range", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_port_range))); - variables->insert("hash_read_ahead", new utils::VariableValueSlot(rak::ptr_fn(torrent::hash_read_ahead), rak::ptr_fn(&apply_hash_read_ahead))); variables->insert("hash_interval", new utils::VariableValueSlot(rak::ptr_fn(torrent::hash_interval), rak::ptr_fn(&apply_hash_interval))); @@ -424,23 +316,10 @@ initialize_variables() { variables->insert("load_start", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_load_start))); variables->insert("load_start_verbose", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_load_start_verbose))); - variables->insert("start_tied", new utils::VariableVoidSlot(rak::ptr_fn(&apply_start_tied))); - variables->insert("stop_untied", new utils::VariableVoidSlot(rak::ptr_fn(&apply_stop_untied))); - variables->insert("close_untied", new utils::VariableVoidSlot(rak::ptr_fn(&apply_close_untied))); - variables->insert("remove_untied", new utils::VariableVoidSlot(rak::ptr_fn(&apply_remove_untied))); - variables->insert("close_low_diskspace", new utils::VariableValueSlot(rak::value_fn(int64_t()), rak::ptr_fn(&apply_close_low_diskspace))); variables->insert("enable_trackers", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_enable_trackers))); variables->insert("encoding_list", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_encoding_list))); - - ADD_COMMAND_SLOT("encryption", call_list, rak::ptr_fn(&apply_encryption)); - - // Move to command_ui.cc. - variables->insert("print", new utils::VariableStringSlot(NULL, rak::mem_fn(control->core(), &core::Manager::push_log))); - - variables->insert("view_add", new utils::VariableStringSlot(NULL, rak::mem_fn(control->view_manager(), &core::ViewManager::insert_throw))); - ADD_VARIABLE_STRING("key_layout", "qwerty"); } template diff --git a/src/option_handler_rules.h b/src/option_handler_rules.h index 9f8476b9..5124dfd1 100644 --- a/src/option_handler_rules.h +++ b/src/option_handler_rules.h @@ -39,9 +39,5 @@ class Control; -void initialize_variables(); -void initialize_download_variables(); -void initialize_command_events(); -void initialize_command_ui(); #endif diff --git a/src/rpc/xmlrpc.h b/src/rpc/xmlrpc.h index 99cc99f6..493f699b 100644 --- a/src/rpc/xmlrpc.h +++ b/src/rpc/xmlrpc.h @@ -51,7 +51,7 @@ namespace rpc { class XmlRpc { public: typedef rak::function2 slot_write; - typedef rak::function2 slot_call_command; + typedef rak::function2 slot_call_command; XmlRpc(); ~XmlRpc(); diff --git a/src/utils/command_slot.cc b/src/utils/command_slot.cc index 57448503..497a4d81 100644 --- a/src/utils/command_slot.cc +++ b/src/utils/command_slot.cc @@ -40,7 +40,7 @@ namespace utils { -const torrent::Object& +const torrent::Object CommandSlot::call_list(Variable* rawVariable, const torrent::Object& rawArgs) { CommandSlot* command = static_cast(rawVariable); @@ -74,13 +74,29 @@ CommandSlot::call_list(Variable* rawVariable, const torrent::Object& rawArgs) { // case torrent::Object::TYPE_STRING: // break; case torrent::Object::TYPE_LIST: - command->m_slot(rawArgs); - break; + return command->m_slot(rawArgs); default: throw torrent::input_error("Not a list."); } +} - return m_emptyObject; +const torrent::Object +CommandSlot::call_string(Variable* rawVariable, const torrent::Object& rawArgs) { + CommandSlot* command = static_cast(rawVariable); + + const torrent::Object& arg = to_single_argument(rawArgs); + + switch (arg.type()) { +// case torrent::Object::TYPE_VALUE: +// break; + + case torrent::Object::TYPE_STRING: + return command->m_slot(arg); + break; + + default: + throw torrent::input_error("Not a string."); + } } // const torrent::Object& diff --git a/src/utils/command_slot.h b/src/utils/command_slot.h index 55a758d5..4760b437 100644 --- a/src/utils/command_slot.h +++ b/src/utils/command_slot.h @@ -37,6 +37,7 @@ #ifndef RTORRENT_UTILS_COMMAND_SLOT_H #define RTORRENT_UTILS_COMMAND_SLOT_H +#include #include #include #include @@ -53,8 +54,7 @@ namespace utils { class CommandSlot : public Variable { public: - // For now, only return void. - typedef rak::function1 slot_type; + typedef rak::function1 slot_type; // template // CommandSlot(SlotSet* slotSet) { @@ -69,7 +69,8 @@ public: void set_slot(slot_type::base_type* s) { m_slot.set(s); } - static const torrent::Object& call_list(Variable* rawVariable, const torrent::Object& args); + static const torrent::Object call_list(Variable* rawVariable, const torrent::Object& args); + static const torrent::Object call_string(Variable* rawVariable, const torrent::Object& args); // static const torrent::Object& get_list(Variable* rawVariable, const torrent::Object& args); @@ -77,6 +78,64 @@ private: slot_type m_slot; }; +// Some slots that convert torrent::Object arguments to proper +// function calls. + +template +class object_void_fn_t : public rak::function_base1 { +public: + object_void_fn_t(Func func) : m_func(func) {} + + virtual torrent::Object operator () (const torrent::Object& arg1) { return torrent::Object(m_func()); } + +private: + Func m_func; +}; + +template +class object_void_fn_t : public rak::function_base1 { +public: + object_void_fn_t(Func func) : m_func(func) {} + + virtual torrent::Object operator () (const torrent::Object& arg1) { + m_func(); + return torrent::Object(); + } + +private: + Func m_func; +}; + +template +class object_string_fn1_t : public rak::function_base1 { +public: + object_string_fn1_t(Func func) : m_func(func) {} + + virtual torrent::Object operator () (const torrent::Object& arg1) { return torrent::Object(m_func(arg1.as_string())); } + +private: + Func m_func; +}; + +template +class object_string_fn1_t : public rak::function_base1 { +public: + object_string_fn1_t(Func func) : m_func(func) {} + + virtual torrent::Object operator () (const torrent::Object& arg1) { + m_func(arg1.as_string()); + + return torrent::Object(); + } + +private: + Func m_func; +}; + +template object_void_fn_t* object_fn(Return (*func)(void)) { return new object_void_fn_t(func); } + +template object_string_fn1_t* object_string_fn(Func func) { return new object_string_fn1_t(func); } + } #endif diff --git a/src/utils/command_variable.cc b/src/utils/command_variable.cc index 23996638..bbb229f4 100644 --- a/src/utils/command_variable.cc +++ b/src/utils/command_variable.cc @@ -40,7 +40,10 @@ namespace utils { -const torrent::Object& +extern CommandVariable commandVariables[10]; +extern CommandVariable* commandVariablesItr; + +const torrent::Object CommandVariable::set_bool(Variable* rawVariable, const torrent::Object& rawArgs) { CommandVariable* variable = static_cast(rawVariable); @@ -71,14 +74,14 @@ CommandVariable::set_bool(Variable* rawVariable, const torrent::Object& rawArgs) return variable->m_variable; } -const torrent::Object& +const torrent::Object CommandVariable::get_bool(Variable* rawVariable, const torrent::Object& args) { CommandVariable* variable = static_cast(rawVariable); return variable->m_variable; } -const torrent::Object& +const torrent::Object CommandVariable::set_value(Variable* rawVariable, const torrent::Object& rawArgs) { CommandVariable* variable = static_cast(rawVariable); @@ -107,14 +110,14 @@ CommandVariable::set_value(Variable* rawVariable, const torrent::Object& rawArgs return variable->m_variable; } -const torrent::Object& +const torrent::Object CommandVariable::get_value(Variable* rawVariable, const torrent::Object& args) { CommandVariable* variable = static_cast(rawVariable); return variable->m_variable; } -const torrent::Object& +const torrent::Object CommandVariable::set_string(Variable* rawVariable, const torrent::Object& rawArgs) { CommandVariable* variable = static_cast(rawVariable); @@ -140,7 +143,7 @@ CommandVariable::set_string(Variable* rawVariable, const torrent::Object& rawArg return variable->m_variable; } -const torrent::Object& +const torrent::Object CommandVariable::get_string(Variable* rawVariable, const torrent::Object& args) { CommandVariable* variable = static_cast(rawVariable); diff --git a/src/utils/command_variable.h b/src/utils/command_variable.h index 6c8a208d..052b21ac 100644 --- a/src/utils/command_variable.h +++ b/src/utils/command_variable.h @@ -50,17 +50,17 @@ class CommandVariable : public Variable { public: CommandVariable(const torrent::Object& v = torrent::Object()) : m_variable(v) {} - const torrent::Object& variable() const { return m_variable; } - void set_variable(const torrent::Object& var) { m_variable = var; } + const torrent::Object variable() const { return m_variable; } + void set_variable(const torrent::Object& var) { m_variable = var; } - static const torrent::Object& set_bool(Variable* rawVariable, const torrent::Object& args); - static const torrent::Object& get_bool(Variable* rawVariable, const torrent::Object& args); + static const torrent::Object set_bool(Variable* rawVariable, const torrent::Object& args); + static const torrent::Object get_bool(Variable* rawVariable, const torrent::Object& args); - static const torrent::Object& set_value(Variable* rawVariable, const torrent::Object& args); - static const torrent::Object& get_value(Variable* rawVariable, const torrent::Object& args); + static const torrent::Object set_value(Variable* rawVariable, const torrent::Object& args); + static const torrent::Object get_value(Variable* rawVariable, const torrent::Object& args); - static const torrent::Object& set_string(Variable* rawVariable, const torrent::Object& args); - static const torrent::Object& get_string(Variable* rawVariable, const torrent::Object& args); + static const torrent::Object set_string(Variable* rawVariable, const torrent::Object& args); + static const torrent::Object get_string(Variable* rawVariable, const torrent::Object& args); private: torrent::Object m_variable; diff --git a/src/utils/variable_map.cc b/src/utils/variable_map.cc index 367ad7a6..bca5a66c 100644 --- a/src/utils/variable_map.cc +++ b/src/utils/variable_map.cc @@ -71,7 +71,7 @@ VariableMap::insert(key_type key, Variable* variable, generic_slot genericSlot, base_type::insert(itr, value_type(key, variable_map_data_type(variable, genericSlot, NULL, flags))); } -const VariableMap::mapped_type& +const VariableMap::mapped_type VariableMap::get(key_type key) const { const_iterator itr = base_type::find(key); @@ -84,7 +84,7 @@ VariableMap::get(key_type key) const { return itr->second.m_variable->get(); } -const VariableMap::mapped_type& +const VariableMap::mapped_type VariableMap::get_d(core::Download* download, key_type key) const { const_iterator itr = base_type::find(key); @@ -266,7 +266,7 @@ VariableMap::process_file(key_type path) { return true; } -const VariableMap::mapped_type& +const VariableMap::mapped_type VariableMap::call_command(key_type key, const mapped_type& arg) { const_iterator itr = base_type::find(key); @@ -279,7 +279,7 @@ VariableMap::call_command(key_type key, const mapped_type& arg) { return itr->second.m_genericSlot(itr->second.m_variable, arg); } -const VariableMap::mapped_type& +const VariableMap::mapped_type VariableMap::call_command_get(key_type key, const mapped_type& arg) { const_iterator itr = base_type::find(key); @@ -292,7 +292,7 @@ VariableMap::call_command_get(key_type key, const mapped_type& arg) { return get(key); } -const VariableMap::mapped_type& +const VariableMap::mapped_type VariableMap::call_command_set(key_type key, const mapped_type& arg) { const_iterator itr = base_type::find(key); diff --git a/src/utils/variable_map.h b/src/utils/variable_map.h index 86919036..56e4f6a6 100644 --- a/src/utils/variable_map.h +++ b/src/utils/variable_map.h @@ -63,8 +63,8 @@ struct variable_map_data_type { // Some commands will need to share data, like get/set a variable. So // instead of using a single virtual member function, each command // will register a member function pointer to be used instead. - typedef const torrent::Object& (*generic_slot)(Variable*, const torrent::Object&); - typedef const torrent::Object& (*download_slot)(Variable*, core::Download*, const torrent::Object&); + typedef const torrent::Object (*generic_slot)(Variable*, const torrent::Object&); + typedef const torrent::Object (*download_slot)(Variable*, core::Download*, const torrent::Object&); variable_map_data_type(Variable* variable, generic_slot genericSlot, download_slot downloadSlot, int flags) : m_variable(variable), m_genericSlot(genericSlot), m_downloadSlot(downloadSlot), m_flags(flags) {} @@ -108,11 +108,11 @@ public: // Consider uninlining the helper functions. - const mapped_type& get(key_type key) const; - const mapped_type& get_d(core::Download* download, key_type key) const; + const mapped_type get(key_type key) const; + const mapped_type get_d(core::Download* download, key_type key) const; - const std::string& get_string(key_type key) const { return get(key).as_string(); } - const std::string& get_d_string(core::Download* download, key_type key) const { return get_d(download, key).as_string(); } + const std::string get_string(key_type key) const { return get(key).as_string(); } + const std::string get_d_string(core::Download* download, key_type key) const { return get_d(download, key).as_string(); } mapped_value_type get_value(key_type key) const { return get(key).as_value(); } mapped_value_type get_d_value(core::Download* download, key_type key) const { return get_d(download, key).as_value(); } @@ -143,10 +143,10 @@ public: // 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(key_type key, const mapped_type& arg); + const mapped_type call_command(key_type key, const mapped_type& arg); - 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); + 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&);