diff --git a/src/Makefile.am b/src/Makefile.am index d61fb484..33ab8891 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,6 +13,7 @@ libsub_root_a_SOURCES = \ command_dynamic.cc \ command_events.cc \ command_file.cc \ + command_ip.cc \ command_helpers.cc \ command_helpers.h \ command_groups.cc \ diff --git a/src/command_helpers.cc b/src/command_helpers.cc index 8a716757..59892f13 100644 --- a/src/command_helpers.cc +++ b/src/command_helpers.cc @@ -46,6 +46,7 @@ void initialize_command_dynamic(); void initialize_command_download(); void initialize_command_events(); void initialize_command_file(); +void initialize_command_ip(); void initialize_command_peer(); void initialize_command_local(); void initialize_command_network(); @@ -65,6 +66,7 @@ initialize_commands() { initialize_command_ui(); initialize_command_download(); initialize_command_file(); + initialize_command_ip(); initialize_command_peer(); initialize_command_throttle(); initialize_command_tracker(); diff --git a/src/command_ip.cc b/src/command_ip.cc new file mode 100644 index 00000000..b10a279b --- /dev/null +++ b/src/command_ip.cc @@ -0,0 +1,247 @@ +// rTorrent - BitTorrent client +// Copyright (C) 2005-2011, 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 + +#include "globals.h" +#include "command_helpers.h" + +void +ipv4_filter_parse(const char* address, int value) { + uint32_t ip_values[4] = { 0, 0, 0, 0 }; + unsigned int block = rpc::ipv4_table::mask_bits; + + char ip_dot; + int values_read; + + if ((values_read = sscanf(address, "%u%1[.]%u%1[.]%u%1[.]%u/%u", + ip_values + 0, &ip_dot, + ip_values + 1, &ip_dot, + ip_values + 2, &ip_dot, + ip_values + 3, + &block)) < 2 || + + // Make sure the dot is included. + (values_read < 7 && values_read % 2) || + + ip_values[0] >= 256 || + ip_values[1] >= 256 || + ip_values[2] >= 256 || + ip_values[3] >= 256 || + + block > rpc::ipv4_table::mask_bits) + throw torrent::input_error("Invalid address format."); + + // E.g. '10.10.' will be '10.10.0.0/16'. + if (values_read < 7) + block = 8 * (values_read / 2); + + torrent::PeerList::ipv4_filter()->insert((ip_values[0] << 24) + (ip_values[1] << 16) + (ip_values[2] << 8) + ip_values[3], + rpc::ipv4_table::mask_bits - block, value); +} + +torrent::Object +apply_ip_tables_insert_table(const std::string& args) { + if (ip_tables.find(args) != ip_tables.end()) + throw torrent::input_error("IP table already exists."); + + ip_tables.insert(args); + return torrent::Object(); +} + +torrent::Object +apply_ip_tables_get(const torrent::Object::list_type& args) { + if (args.size() != 2) + throw torrent::input_error("Incorrect number of arguments."); + + torrent::Object::list_const_iterator args_itr = args.begin(); + + const std::string& name = (args_itr++)->as_string(); + const std::string& address = (args_itr++)->as_string(); + + // Move to a helper function, add support for addresses. + uint32_t ip_values[4]; + + if (sscanf(address.c_str(), "%u.%u.%u.%u", + ip_values + 0, ip_values + 1, ip_values + 2, ip_values + 3) != 4) + throw torrent::input_error("Invalid address format."); + + rpc::ip_table_list::iterator table_itr = ip_tables.find(name); + + if (table_itr == ip_tables.end()) + throw torrent::input_error("Could not find ip table."); + + return table_itr->table.at((ip_values[0] << 24) + (ip_values[1] << 16) + (ip_values[2] << 8) + ip_values[3]); +} + +torrent::Object +apply_ip_tables_add_address(const torrent::Object::list_type& args) { + if (args.size() != 3) + throw torrent::input_error("Incorrect number of arguments."); + + torrent::Object::list_const_iterator args_itr = args.begin(); + + const std::string& name = (args_itr++)->as_string(); + const std::string& address = (args_itr++)->as_string(); + const std::string& value_str = (args_itr++)->as_string(); + + // Move to a helper function, add support for addresses. + uint32_t ip_values[4]; + unsigned int block = rpc::ipv4_table::mask_bits; + + if (sscanf(address.c_str(), "%u.%u.%u.%u/%u", + ip_values + 0, ip_values + 1, ip_values + 2, ip_values + 3, &block) < 4 || + block > rpc::ipv4_table::mask_bits) + throw torrent::input_error("Invalid address format."); + + int value; + + if (value_str == "block") + value = 1; + else + throw torrent::input_error("Invalid value."); + + rpc::ip_table_list::iterator table_itr = ip_tables.find(name); + + if (table_itr == ip_tables.end()) + throw torrent::input_error("Could not find ip table."); + + table_itr->table.insert((ip_values[0] << 24) + (ip_values[1] << 16) + (ip_values[2] << 8) + ip_values[3], + rpc::ipv4_table::mask_bits - block, value); + + return torrent::Object(); +} + +// +// IPv4 filter functions: +// + +torrent::Object +apply_ipv4_filter_size_data() { + return torrent::PeerList::ipv4_filter()->sizeof_data(); +} + +torrent::Object +apply_ipv4_filter_get(const std::string& args) { + // Move to a helper function, add support for addresses. + uint32_t ip_values[4]; + + if (sscanf(args.c_str(), "%u.%u.%u.%u", + ip_values + 0, ip_values + 1, ip_values + 2, ip_values + 3) != 4) + throw torrent::input_error("Invalid address format."); + + return torrent::PeerList::ipv4_filter()->at((ip_values[0] << 24) + (ip_values[1] << 16) + (ip_values[2] << 8) + ip_values[3]); +} + +torrent::Object +apply_ipv4_filter_add_address(const torrent::Object::list_type& args) { + if (args.size() != 2) + throw torrent::input_error("Incorrect number of arguments."); + + ipv4_filter_parse(args.front().as_string().c_str(), + torrent::option_find_string(torrent::OPTION_IP_FILTER, args.back().as_string().c_str())); + return torrent::Object(); +} + +torrent::Object +apply_ipv4_filter_load(const torrent::Object::list_type& args) { + if (args.size() != 2) + throw torrent::input_error("Incorrect number of arguments."); + + torrent::Object::list_const_iterator args_itr = args.begin(); + + std::fstream file(rak::path_expand(args.front().as_string()).c_str(), std::ios::in); + + if (!file.is_open()) + throw torrent::input_error("Could not open ip filter file: " + args.front().as_string()); + + int value = torrent::option_find_string(torrent::OPTION_IP_FILTER, args.back().as_string().c_str()); + + char buffer[4096]; + unsigned int lineNumber = 0; + + try { + while (file.good() && !file.getline(buffer, 4096).fail()) { + if (file.gcount() == 0) + throw torrent::internal_error("parse_command_file(...) file.gcount() == 0."); + + int lineLength = file.gcount() - 1; + // In case we are at the end of the file and the last character is + // not a line feed, we'll just increase the read character count so + // that the last would also be included in option line. + if (file.eof() && file.get() != '\n') + lineLength++; + + lineNumber++; + + if (buffer[0] == '\0' || buffer[0] == '#') + continue; + + ipv4_filter_parse(buffer, value); + } + + } catch (torrent::input_error& e) { + snprintf(buffer, 2048, "Error in ip filter file: %s:%u: %s", args.front().as_string().c_str(), lineNumber, e.what()); + + throw torrent::input_error(buffer); + } + + lt_log_print(torrent::LOG_CONNECTION_INFO, "Loaded %u %s address blocks (%u kb in-memory) from '%s'.", + lineNumber, + args.back().as_string().c_str(), + torrent::PeerList::ipv4_filter()->sizeof_data() / 1024, + args.front().as_string().c_str()); + + return torrent::Object(); +} + +void +initialize_command_ip() { + CMD2_ANY_STRING ("ip_tables.insert_table", std::bind(&apply_ip_tables_insert_table, std::placeholders::_2)); + CMD2_ANY_LIST ("ip_tables.get", std::bind(&apply_ip_tables_get, std::placeholders::_2)); + CMD2_ANY_LIST ("ip_tables.add_address", std::bind(&apply_ip_tables_add_address, std::placeholders::_2)); + + CMD2_ANY ("ipv4_filter.size_data", std::bind(&apply_ipv4_filter_size_data)); + CMD2_ANY_STRING ("ipv4_filter.get", std::bind(&apply_ipv4_filter_get, std::placeholders::_2)); + CMD2_ANY_LIST ("ipv4_filter.add_address", std::bind(&apply_ipv4_filter_add_address, std::placeholders::_2)); + CMD2_ANY_LIST ("ipv4_filter.load", std::bind(&apply_ipv4_filter_load, std::placeholders::_2)); +} diff --git a/src/command_network.cc b/src/command_network.cc index d32a92b8..05b00410 100644 --- a/src/command_network.cc +++ b/src/command_network.cc @@ -37,24 +37,20 @@ #include "config.h" #include -#include #include #include #include #include #include -#include #include #include #include #include #include #include -#include #include #include -#include "core/dht_manager.h" #include "core/download.h" #include "core/manager.h" #include "rpc/scgi.h" @@ -100,56 +96,6 @@ torrent::Object apply_hash_read_ahead(int arg) { torrent::set_hash_ torrent::Object apply_hash_interval(int arg) { torrent::set_hash_interval(arg * 1000); return torrent::Object(); } torrent::Object apply_encoding_list(const std::string& arg) { torrent::encoding_list()->push_back(arg); return torrent::Object(); } -struct call_add_node_t { - call_add_node_t(int port) : m_port(port) { } - - void operator() (const sockaddr* sa, int err) { - if (sa == NULL) { - lt_log_print(torrent::LOG_DHT_WARN, "Could not resolve host."); - } else { - torrent::dht_manager()->add_node(sa, m_port); - } - } - - int m_port; -}; - -torrent::Object -apply_dht_add_node(const std::string& arg) { - if (!torrent::dht_manager()->is_valid()) - throw torrent::input_error("DHT not enabled."); - - int port, ret; - char dummy; - char host[1024]; - - ret = std::sscanf(arg.c_str(), "%1023[^:]:%i%c", host, &port, &dummy); - - if (ret == 1) - port = 6881; - else if (ret != 2) - throw torrent::input_error("Could not parse host."); - - if (port < 1 || port > 65535) - throw torrent::input_error("Invalid port number."); - - torrent::connection_manager()->resolver()(host, (int)rak::socket_address::pf_inet, SOCK_DGRAM, call_add_node_t(port)); - return torrent::Object(); -} - -torrent::Object -apply_enable_trackers(int64_t arg) { - for (core::Manager::DListItr itr = control->core()->download_list()->begin(), last = control->core()->download_list()->end(); itr != last; ++itr) { - std::for_each((*itr)->tracker_list()->begin(), (*itr)->tracker_list()->end(), - arg ? std::mem_fun(&torrent::Tracker::enable) : std::mem_fun(&torrent::Tracker::disable)); - - if (arg && !rpc::call_command_value("trackers.use_udp")) - (*itr)->enable_udp_trackers(false); - } - - return torrent::Object(); -} - torrent::File* xmlrpc_find_file(core::Download* download, uint32_t index) { if (index >= download->file_list()->size_files()) @@ -284,199 +230,6 @@ apply_xmlrpc_dialect(const std::string& arg) { return torrent::Object(); } -// -// IP filter stuff: -// - -void -ipv4_filter_parse(const char* address, int value) { - uint32_t ip_values[4] = { 0, 0, 0, 0 }; - unsigned int block = rpc::ipv4_table::mask_bits; - - char ip_dot; - int values_read; - - if ((values_read = sscanf(address, "%u%1[.]%u%1[.]%u%1[.]%u/%u", - ip_values + 0, &ip_dot, - ip_values + 1, &ip_dot, - ip_values + 2, &ip_dot, - ip_values + 3, - &block)) < 2 || - - // Make sure the dot is included. - (values_read < 7 && values_read % 2) || - - ip_values[0] >= 256 || - ip_values[1] >= 256 || - ip_values[2] >= 256 || - ip_values[3] >= 256 || - - block > rpc::ipv4_table::mask_bits) - throw torrent::input_error("Invalid address format."); - - // E.g. '10.10.' will be '10.10.0.0/16'. - if (values_read < 7) - block = 8 * (values_read / 2); - - torrent::PeerList::ipv4_filter()->insert((ip_values[0] << 24) + (ip_values[1] << 16) + (ip_values[2] << 8) + ip_values[3], - rpc::ipv4_table::mask_bits - block, value); -} - -torrent::Object -apply_ip_tables_insert_table(const std::string& args) { - if (ip_tables.find(args) != ip_tables.end()) - throw torrent::input_error("IP table already exists."); - - ip_tables.insert(args); - return torrent::Object(); -} - -torrent::Object -apply_ip_tables_get(const torrent::Object::list_type& args) { - if (args.size() != 2) - throw torrent::input_error("Incorrect number of arguments."); - - torrent::Object::list_const_iterator args_itr = args.begin(); - - const std::string& name = (args_itr++)->as_string(); - const std::string& address = (args_itr++)->as_string(); - - // Move to a helper function, add support for addresses. - uint32_t ip_values[4]; - - if (sscanf(address.c_str(), "%u.%u.%u.%u", - ip_values + 0, ip_values + 1, ip_values + 2, ip_values + 3) != 4) - throw torrent::input_error("Invalid address format."); - - rpc::ip_table_list::iterator table_itr = ip_tables.find(name); - - if (table_itr == ip_tables.end()) - throw torrent::input_error("Could not find ip table."); - - return table_itr->table.at((ip_values[0] << 24) + (ip_values[1] << 16) + (ip_values[2] << 8) + ip_values[3]); -} - -torrent::Object -apply_ip_tables_add_address(const torrent::Object::list_type& args) { - if (args.size() != 3) - throw torrent::input_error("Incorrect number of arguments."); - - torrent::Object::list_const_iterator args_itr = args.begin(); - - const std::string& name = (args_itr++)->as_string(); - const std::string& address = (args_itr++)->as_string(); - const std::string& value_str = (args_itr++)->as_string(); - - // Move to a helper function, add support for addresses. - uint32_t ip_values[4]; - unsigned int block = rpc::ipv4_table::mask_bits; - - if (sscanf(address.c_str(), "%u.%u.%u.%u/%u", - ip_values + 0, ip_values + 1, ip_values + 2, ip_values + 3, &block) < 4 || - block > rpc::ipv4_table::mask_bits) - throw torrent::input_error("Invalid address format."); - - int value; - - if (value_str == "block") - value = 1; - else - throw torrent::input_error("Invalid value."); - - rpc::ip_table_list::iterator table_itr = ip_tables.find(name); - - if (table_itr == ip_tables.end()) - throw torrent::input_error("Could not find ip table."); - - table_itr->table.insert((ip_values[0] << 24) + (ip_values[1] << 16) + (ip_values[2] << 8) + ip_values[3], - rpc::ipv4_table::mask_bits - block, value); - - return torrent::Object(); -} - -// -// IPv4 filter functions: -// - -torrent::Object -apply_ipv4_filter_size_data() { - return torrent::PeerList::ipv4_filter()->sizeof_data(); -} - -torrent::Object -apply_ipv4_filter_get(const std::string& args) { - // Move to a helper function, add support for addresses. - uint32_t ip_values[4]; - - if (sscanf(args.c_str(), "%u.%u.%u.%u", - ip_values + 0, ip_values + 1, ip_values + 2, ip_values + 3) != 4) - throw torrent::input_error("Invalid address format."); - - return torrent::PeerList::ipv4_filter()->at((ip_values[0] << 24) + (ip_values[1] << 16) + (ip_values[2] << 8) + ip_values[3]); -} - -torrent::Object -apply_ipv4_filter_add_address(const torrent::Object::list_type& args) { - if (args.size() != 2) - throw torrent::input_error("Incorrect number of arguments."); - - ipv4_filter_parse(args.front().as_string().c_str(), - torrent::option_find_string(torrent::OPTION_IP_FILTER, args.back().as_string().c_str())); - return torrent::Object(); -} - -torrent::Object -apply_ipv4_filter_load(const torrent::Object::list_type& args) { - if (args.size() != 2) - throw torrent::input_error("Incorrect number of arguments."); - - torrent::Object::list_const_iterator args_itr = args.begin(); - - std::fstream file(rak::path_expand(args.front().as_string()).c_str(), std::ios::in); - - if (!file.is_open()) - throw torrent::input_error("Could not open ip filter file: " + args.front().as_string()); - - int value = torrent::option_find_string(torrent::OPTION_IP_FILTER, args.back().as_string().c_str()); - - char buffer[4096]; - unsigned int lineNumber = 0; - - try { - while (file.good() && !file.getline(buffer, 4096).fail()) { - if (file.gcount() == 0) - throw torrent::internal_error("parse_command_file(...) file.gcount() == 0."); - - int lineLength = file.gcount() - 1; - // In case we are at the end of the file and the last character is - // not a line feed, we'll just increase the read character count so - // that the last would also be included in option line. - if (file.eof() && file.get() != '\n') - lineLength++; - - lineNumber++; - - if (buffer[0] == '\0' || buffer[0] == '#') - continue; - - ipv4_filter_parse(buffer, value); - } - - } catch (torrent::input_error& e) { - snprintf(buffer, 2048, "Error in ip filter file: %s:%u: %s", args.front().as_string().c_str(), lineNumber, e.what()); - - throw torrent::input_error(buffer); - } - - lt_log_print(torrent::LOG_CONNECTION_INFO, "Loaded %u %s address blocks (%u kb in-memory) from '%s'.", - lineNumber, - args.back().as_string().c_str(), - torrent::PeerList::ipv4_filter()->sizeof_data() / 1024, - args.front().as_string().c_str()); - - return torrent::Object(); -} - void initialize_command_network() { torrent::ConnectionManager* cm = torrent::connection_manager(); @@ -557,27 +310,4 @@ initialize_command_network() { CMD2_ANY_VALUE_V ("system.hash.interval.set", std::bind(&apply_hash_interval, std::placeholders::_2)); CMD2_ANY ("system.hash.max_tries", std::bind(&torrent::hash_max_tries)); CMD2_ANY_VALUE_V ("system.hash.max_tries.set", std::bind(&torrent::set_hash_max_tries, std::placeholders::_2)); - - CMD2_ANY_VALUE ("trackers.enable", std::bind(&apply_enable_trackers, int64_t(1))); - CMD2_ANY_VALUE ("trackers.disable", std::bind(&apply_enable_trackers, int64_t(0))); - CMD2_VAR_VALUE ("trackers.numwant", -1); - CMD2_VAR_BOOL ("trackers.use_udp", true); - - CMD2_ANY_STRING ("ip_tables.insert_table", std::bind(&apply_ip_tables_insert_table, std::placeholders::_2)); - CMD2_ANY_LIST ("ip_tables.get", std::bind(&apply_ip_tables_get, std::placeholders::_2)); - CMD2_ANY_LIST ("ip_tables.add_address", std::bind(&apply_ip_tables_add_address, std::placeholders::_2)); - - CMD2_ANY ("ipv4_filter.size_data", std::bind(&apply_ipv4_filter_size_data)); - CMD2_ANY_STRING ("ipv4_filter.get", std::bind(&apply_ipv4_filter_get, std::placeholders::_2)); - CMD2_ANY_LIST ("ipv4_filter.add_address", std::bind(&apply_ipv4_filter_add_address, std::placeholders::_2)); - CMD2_ANY_LIST ("ipv4_filter.load", std::bind(&apply_ipv4_filter_load, std::placeholders::_2)); - -// CMD2_ANY_V ("dht.enable", std::bind(&core::DhtManager::set_start, control->dht_manager())); -// CMD2_ANY_V ("dht.disable", std::bind(&core::DhtManager::set_stop, control->dht_manager())); - CMD2_ANY_STRING_V("dht.mode.set", std::bind(&core::DhtManager::set_mode, control->dht_manager(), std::placeholders::_2)); - CMD2_VAR_VALUE ("dht.port", int64_t(6881)); - CMD2_ANY_STRING ("dht.add_node", std::bind(&apply_dht_add_node, std::placeholders::_2)); - CMD2_ANY ("dht.statistics", std::bind(&core::DhtManager::dht_statistics, control->dht_manager())); - CMD2_ANY ("dht.throttle.name", std::bind(&core::DhtManager::throttle_name, control->dht_manager())); - CMD2_ANY_STRING_V("dht.throttle.name.set", std::bind(&core::DhtManager::set_throttle_name, control->dht_manager(), std::placeholders::_2)); } diff --git a/src/command_tracker.cc b/src/command_tracker.cc index b97a5d4b..c62f0e60 100644 --- a/src/command_tracker.cc +++ b/src/command_tracker.cc @@ -36,14 +36,19 @@ #include "config.h" +#include #include +#include #include +#include +#include "core/download.h" #include "core/manager.h" #include "globals.h" #include "control.h" #include "command_helpers.h" +#include "core/dht_manager.h" void tracker_set_enabled(torrent::Tracker* tracker, bool state) { @@ -53,6 +58,56 @@ tracker_set_enabled(torrent::Tracker* tracker, bool state) { tracker->disable(); } +struct call_add_node_t { + call_add_node_t(int port) : m_port(port) { } + + void operator() (const sockaddr* sa, int err) { + if (sa == NULL) { + lt_log_print(torrent::LOG_DHT_WARN, "Could not resolve host."); + } else { + torrent::dht_manager()->add_node(sa, m_port); + } + } + + int m_port; +}; + +torrent::Object +apply_dht_add_node(const std::string& arg) { + if (!torrent::dht_manager()->is_valid()) + throw torrent::input_error("DHT not enabled."); + + int port, ret; + char dummy; + char host[1024]; + + ret = std::sscanf(arg.c_str(), "%1023[^:]:%i%c", host, &port, &dummy); + + if (ret == 1) + port = 6881; + else if (ret != 2) + throw torrent::input_error("Could not parse host."); + + if (port < 1 || port > 65535) + throw torrent::input_error("Invalid port number."); + + torrent::connection_manager()->resolver()(host, (int)rak::socket_address::pf_inet, SOCK_DGRAM, call_add_node_t(port)); + return torrent::Object(); +} + +torrent::Object +apply_enable_trackers(int64_t arg) { + for (core::Manager::DListItr itr = control->core()->download_list()->begin(), last = control->core()->download_list()->end(); itr != last; ++itr) { + std::for_each((*itr)->tracker_list()->begin(), (*itr)->tracker_list()->end(), + arg ? std::mem_fun(&torrent::Tracker::enable) : std::mem_fun(&torrent::Tracker::disable)); + + if (arg && !rpc::call_command_value("trackers.use_udp")) + (*itr)->enable_udp_trackers(false); + } + + return torrent::Object(); +} + void initialize_command_tracker() { CMD2_TRACKER ("t.is_open", std::bind(&torrent::Tracker::is_busy, std::placeholders::_1)); @@ -87,4 +142,16 @@ initialize_command_tracker() { CMD2_TRACKER ("t.scrape_complete", std::bind(&torrent::Tracker::scrape_complete, std::placeholders::_1)); CMD2_TRACKER ("t.scrape_incomplete", std::bind(&torrent::Tracker::scrape_incomplete, std::placeholders::_1)); CMD2_TRACKER ("t.scrape_downloaded", std::bind(&torrent::Tracker::scrape_downloaded, std::placeholders::_1)); + + CMD2_ANY_VALUE ("trackers.enable", std::bind(&apply_enable_trackers, int64_t(1))); + CMD2_ANY_VALUE ("trackers.disable", std::bind(&apply_enable_trackers, int64_t(0))); + CMD2_VAR_VALUE ("trackers.numwant", -1); + CMD2_VAR_BOOL ("trackers.use_udp", true); + + CMD2_ANY_STRING_V ("dht.mode.set", std::bind(&core::DhtManager::set_mode, control->dht_manager(), std::placeholders::_2)); + CMD2_VAR_VALUE ("dht.port", int64_t(6881)); + CMD2_ANY_STRING ("dht.add_node", std::bind(&apply_dht_add_node, std::placeholders::_2)); + CMD2_ANY ("dht.statistics", std::bind(&core::DhtManager::dht_statistics, control->dht_manager())); + CMD2_ANY ("dht.throttle.name", std::bind(&core::DhtManager::throttle_name, control->dht_manager())); + CMD2_ANY_STRING_V ("dht.throttle.name.set", std::bind(&core::DhtManager::set_throttle_name, control->dht_manager(), std::placeholders::_2)); }