mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-10-05 21:59:21 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 88782d005d | |||
| 5fcd779b15 | |||
| 7104512ac1 | |||
| bd82f6152e | |||
| 83eb4e016a | |||
| 6b60c219fa | |||
| 2804be2c9c | |||
| 21019fde41 | |||
| e4e858cc40 | |||
| 60eb8f0383 | |||
| 072cbae0c6 | |||
| 16bfaf2694 | |||
| c8da93bd30 | |||
| 2cd3ca052d | |||
| 8be1fcb3a4 |
@@ -187,6 +187,7 @@ libsub_root_a_SOURCES = \
|
||||
command_helpers.cc \
|
||||
command_helpers.h \
|
||||
command_groups.cc \
|
||||
command_load.cc \
|
||||
command_local.cc \
|
||||
command_logging.cc \
|
||||
command_network.cc \
|
||||
@@ -195,6 +196,7 @@ libsub_root_a_SOURCES = \
|
||||
command_tracker.cc \
|
||||
command_scheduler.cc \
|
||||
command_string.cc \
|
||||
command_system.cc \
|
||||
command_ui.cc \
|
||||
control.cc \
|
||||
control.h \
|
||||
|
||||
+6
-18
@@ -142,16 +142,6 @@ apply_d_delete_tied(core::Download* download) {
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
void
|
||||
apply_d_directory(core::Download* download, const std::string& name) {
|
||||
if (!download->file_list()->is_multi_file())
|
||||
download->set_root_directory(name);
|
||||
else if (name.empty() || *name.rbegin() == '/')
|
||||
download->set_root_directory(name + download->info()->name().str());
|
||||
else
|
||||
download->set_root_directory(name + "/" + download->info()->name().str());
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_d_connection_type(core::Download* download, const std::string& name) {
|
||||
torrent::Download::ConnectionType t =
|
||||
@@ -718,7 +708,7 @@ initialize_command_download() {
|
||||
CMD2_DL_V ("d.pause", std::bind(&core::DownloadList::pause_default, control->core()->download_list(), std::placeholders::_1));
|
||||
CMD2_DL_V ("d.open", std::bind(&core::DownloadList::open_throw, control->core()->download_list(), std::placeholders::_1));
|
||||
CMD2_DL_V ("d.close", std::bind(&core::DownloadList::close_throw, control->core()->download_list(), std::placeholders::_1));
|
||||
CMD2_DL_V ("d.close.directly", std::bind(&core::DownloadList::close_directly, control->core()->download_list(), std::placeholders::_1));
|
||||
CMD2_DL_V ("d.close.directly", std::bind(&core::DownloadList::close_files, control->core()->download_list(), std::placeholders::_1));
|
||||
CMD2_DL_V ("d.erase", std::bind(&core::DownloadList::erase_ptr, control->core()->download_list(), std::placeholders::_1));
|
||||
CMD2_DL_V ("d.check_hash", std::bind(&core::DownloadList::check_hash, control->core()->download_list(), std::placeholders::_1));
|
||||
|
||||
@@ -884,12 +874,11 @@ initialize_command_download() {
|
||||
CMD2_DL_LIST ("d.tracker.insert", std::bind(&download_tracker_insert, std::placeholders::_1, std::placeholders::_2));
|
||||
CMD2_DL_VALUE_V ("d.tracker.send_scrape", [](auto download, uint64_t arg) { download->tracker_controller().scrape_request(arg); });
|
||||
|
||||
CMD2_DL ("d.directory", CMD2_ON_FL(root_dir));
|
||||
CMD2_DL ("d.directory.realpath.or_empty", [](auto* download, auto) { return resolve_path(download->file_list()->root_dir()); });
|
||||
CMD2_DL ("d.directory.realpath.or_throw", [](auto* download, auto) { return resolve_path_or_throw(download->file_list()->root_dir()); });
|
||||
CMD2_DL_STRING_V("d.directory.set", std::bind(&apply_d_directory, std::placeholders::_1, std::placeholders::_2));
|
||||
CMD2_DL ("d.directory_base", CMD2_ON_FL(root_dir));
|
||||
CMD2_DL_STRING_V("d.directory_base.set", std::bind(&core::Download::set_root_directory, std::placeholders::_1, std::placeholders::_2));
|
||||
CMD2_DL ("d.directory", CMD2_ON_FL(root_dir));
|
||||
CMD2_DL ("d.directory.realpath.or_empty", [](auto* download, auto) { return resolve_path(download->file_list()->root_dir()); });
|
||||
CMD2_DL ("d.directory.realpath.or_throw", [](auto* download, auto) { return resolve_path_or_throw(download->file_list()->root_dir()); });
|
||||
CMD2_DL_STRING_V("d.directory.set", [](auto* download, auto arg) { download->set_directory(arg); });
|
||||
CMD2_DL_STRING_V("d.directory.base.set", [](auto* download, auto arg) { download->set_base_directory(arg); });
|
||||
|
||||
CMD2_DL ("d.priority", std::bind(&core::Download::priority, std::placeholders::_1));
|
||||
CMD2_DL ("d.priority_str", std::bind(&retrieve_d_priority_str, std::placeholders::_1));
|
||||
@@ -950,7 +939,6 @@ initialize_command_download() {
|
||||
rpc::rpc.mark_safe("d.name.or_base64");
|
||||
rpc::rpc.mark_safe("d.name.or_as_binary");
|
||||
rpc::rpc.mark_safe("d.directory");
|
||||
rpc::rpc.mark_safe("d.directory_base");
|
||||
rpc::rpc.mark_safe("d.creation_date");
|
||||
rpc::rpc.mark_safe("d.load_date");
|
||||
rpc::rpc.mark_safe("d.up.rate");
|
||||
|
||||
+1
-36
@@ -1,25 +1,17 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <functional>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <torrent/rate.h>
|
||||
#include <torrent/hash_string.h>
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/utils/log.h>
|
||||
#include <torrent/utils/directory_events.h>
|
||||
#include <torrent/utils/file_stat.h>
|
||||
#include <torrent/utils/string_manip.h>
|
||||
|
||||
#include "globals.h"
|
||||
#include "control.h"
|
||||
#include "command_helpers.h"
|
||||
#include "core/download.h"
|
||||
#include "core/download_list.h"
|
||||
#include "core/manager.h"
|
||||
#include "core/view_manager.h"
|
||||
#include "rpc/command_scheduler.h"
|
||||
#include "rpc/parse.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
#include "utils/watch_ready_queue.h"
|
||||
|
||||
@@ -146,24 +138,6 @@ apply_schedule(const torrent::Object::list_type& args, bool if_absent) {
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_load(const torrent::Object::list_type& args, int flags) {
|
||||
torrent::Object::list_const_iterator argsItr = args.begin();
|
||||
|
||||
if (argsItr == args.end())
|
||||
throw torrent::input_error("Too few arguments.");
|
||||
|
||||
auto& filename = argsItr->as_string();
|
||||
core::Manager::command_list_type commands;
|
||||
|
||||
while (++argsItr != args.end())
|
||||
commands.push_back(argsItr->as_string());
|
||||
|
||||
control->core()->try_create_download_expand(filename, flags, commands);
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
void apply_import(const std::string& path) { if (!rpc::parse_command_file(path)) throw torrent::input_error("Could not open option file: " + path); }
|
||||
void apply_try_import(const std::string& path) { if (!rpc::parse_command_file(path)) control->core()->push_log_std("Could not read resource file: " + path); }
|
||||
|
||||
@@ -368,15 +342,6 @@ initialize_command_events() {
|
||||
CMD2_ANY_STRING_V("import", [](auto, auto& str) { return apply_import(str); });
|
||||
CMD2_ANY_STRING_V("try_import", [](auto, auto& str) { return apply_try_import(str); });
|
||||
|
||||
CMD2_ANY_LIST ("load.normal", [](auto, auto& args) { return apply_load(args, core::Manager::create_quiet | core::Manager::create_tied); });
|
||||
CMD2_ANY_LIST ("load.verbose", [](auto, auto& args) { return apply_load(args, core::Manager::create_tied); });
|
||||
CMD2_ANY_LIST ("load.start", [](auto, auto& args) { return apply_load(args, core::Manager::create_quiet | core::Manager::create_tied | core::Manager::create_start); });
|
||||
CMD2_ANY_LIST ("load.start_verbose", [](auto, auto& args) { return apply_load(args, core::Manager::create_tied | core::Manager::create_start); });
|
||||
CMD2_ANY_LIST ("load.raw", [](auto, auto& args) { return apply_load(args, core::Manager::create_quiet | core::Manager::create_raw_data); });
|
||||
CMD2_ANY_LIST ("load.raw_verbose", [](auto, auto& args) { return apply_load(args, core::Manager::create_raw_data); });
|
||||
CMD2_ANY_LIST ("load.raw_start", [](auto, auto& args) { return apply_load(args, core::Manager::create_quiet | core::Manager::create_start | core::Manager::create_raw_data); });
|
||||
CMD2_ANY_LIST ("load.raw_start_verbose", [](auto, auto& args) { return apply_load(args, core::Manager::create_start | core::Manager::create_raw_data); });
|
||||
|
||||
CMD2_ANY_VALUE ("close_low_diskspace", [](auto, auto& arg) { return apply_close_low_diskspace(arg, 99); });
|
||||
CMD2_ANY_VALUE ("close_low_diskspace.normal", [](auto, auto& arg) { return apply_close_low_diskspace(arg, 3); });
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ void initialize_command_throttle();
|
||||
void initialize_command_tracker();
|
||||
void initialize_command_scheduler();
|
||||
void initialize_command_string();
|
||||
void initialize_command_system();
|
||||
void initialize_command_ui();
|
||||
|
||||
void
|
||||
@@ -39,4 +40,5 @@ initialize_commands() {
|
||||
initialize_command_tracker();
|
||||
initialize_command_scheduler();
|
||||
initialize_command_string();
|
||||
initialize_command_system();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "command_helpers.h"
|
||||
#include "control.h"
|
||||
#include "core/manager.h"
|
||||
|
||||
torrent::Object
|
||||
apply_load_trusted(const torrent::Object::list_type& args, int flags) {
|
||||
auto argsItr = args.begin();
|
||||
|
||||
if (argsItr == args.end())
|
||||
throw torrent::input_error("Too few arguments.");
|
||||
|
||||
auto& filename = argsItr->as_string();
|
||||
|
||||
core::Manager::command_list_type commands;
|
||||
|
||||
while (++argsItr != args.end())
|
||||
commands.push_back(argsItr->as_string());
|
||||
|
||||
control->core()->try_create_download_expand(filename, flags, commands);
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_load_untrusted(const torrent::Object::list_type& args, int flags) {
|
||||
auto argsItr = args.begin();
|
||||
|
||||
if (argsItr == args.end())
|
||||
throw torrent::input_error("Too few arguments.");
|
||||
|
||||
auto& filename = argsItr->as_string();
|
||||
|
||||
core::Manager::command_list_type commands;
|
||||
|
||||
while (++argsItr != args.end())
|
||||
commands.push_back(argsItr->as_string());
|
||||
|
||||
control->core()->try_create_download_untrusted(filename, flags, commands);
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
void
|
||||
initialize_command_load() {
|
||||
CMD2_ANY_LIST ("load.normal", [](auto, auto& args) { return apply_load_trusted(args, core::Manager::create_quiet | core::Manager::create_tied); });
|
||||
CMD2_ANY_LIST ("load.verbose", [](auto, auto& args) { return apply_load_trusted(args, core::Manager::create_tied); });
|
||||
CMD2_ANY_LIST ("load.start", [](auto, auto& args) { return apply_load_trusted(args, core::Manager::create_quiet | core::Manager::create_tied | core::Manager::create_start); });
|
||||
CMD2_ANY_LIST ("load.start_verbose", [](auto, auto& args) { return apply_load_trusted(args, core::Manager::create_tied | core::Manager::create_start); });
|
||||
CMD2_ANY_LIST ("load.raw", [](auto, auto& args) { return apply_load_trusted(args, core::Manager::create_quiet | core::Manager::create_raw_data); });
|
||||
CMD2_ANY_LIST ("load.raw_verbose", [](auto, auto& args) { return apply_load_trusted(args, core::Manager::create_raw_data); });
|
||||
CMD2_ANY_LIST ("load.raw_start", [](auto, auto& args) { return apply_load_trusted(args, core::Manager::create_quiet | core::Manager::create_start | core::Manager::create_raw_data); });
|
||||
CMD2_ANY_LIST ("load.raw_start_verbose", [](auto, auto& args) { return apply_load_trusted(args, core::Manager::create_start | core::Manager::create_raw_data); });
|
||||
|
||||
CMD2_ANY_LIST ("load.untrusted.normal", [](auto, auto& args) { return apply_load_untrusted(args, core::Manager::create_quiet); });
|
||||
CMD2_ANY_LIST ("load.untrusted.verbose", [](auto, auto& args) { return apply_load_untrusted(args, 0); });
|
||||
CMD2_ANY_LIST ("load.untrusted.start", [](auto, auto& args) { return apply_load_untrusted(args, core::Manager::create_quiet | core::Manager::create_start); });
|
||||
CMD2_ANY_LIST ("load.untrusted.start_verbose", [](auto, auto& args) { return apply_load_untrusted(args, core::Manager::create_start); });
|
||||
CMD2_ANY_LIST ("load.untrusted.raw", [](auto, auto& args) { return apply_load_untrusted(args, core::Manager::create_quiet | core::Manager::create_raw_data); });
|
||||
CMD2_ANY_LIST ("load.untrusted.raw_verbose", [](auto, auto& args) { return apply_load_untrusted(args, core::Manager::create_raw_data); });
|
||||
CMD2_ANY_LIST ("load.untrusted.raw_start", [](auto, auto& args) { return apply_load_untrusted(args, core::Manager::create_quiet | core::Manager::create_start | core::Manager::create_raw_data); });
|
||||
CMD2_ANY_LIST ("load.untrusted.raw_start_verbose", [](auto, auto& args) { return apply_load_untrusted(args, core::Manager::create_start | core::Manager::create_raw_data); });
|
||||
|
||||
CMD2_ANY_VALUE_V("load.untrusted.mark_safe", [](auto, auto& arg) {
|
||||
if (arg == 0)
|
||||
return;
|
||||
|
||||
// TODO: Add a bool to core::Manager.
|
||||
|
||||
rpc::rpc.mark_safe("load.untrusted.normal");
|
||||
rpc::rpc.mark_safe("load.untrusted.verbose");
|
||||
rpc::rpc.mark_safe("load.untrusted.start");
|
||||
rpc::rpc.mark_safe("load.untrusted.start_verbose");
|
||||
rpc::rpc.mark_safe("load.untrusted.raw");
|
||||
rpc::rpc.mark_safe("load.untrusted.raw_verbose");
|
||||
rpc::rpc.mark_safe("load.untrusted.raw_start");
|
||||
rpc::rpc.mark_safe("load.untrusted.raw_start_verbose");
|
||||
});
|
||||
|
||||
}
|
||||
+8
-186
@@ -1,34 +1,16 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <cerrno>
|
||||
#include <fcntl.h>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <torrent/torrent.h>
|
||||
#include <torrent/data/file_manager.h>
|
||||
#include <torrent/data/chunk_utils.h>
|
||||
#include <torrent/runtime/runtime.h>
|
||||
#include <torrent/runtime/memory_manager.h>
|
||||
#include <torrent/runtime/socket_manager.h>
|
||||
#include <torrent/utils/chrono.h>
|
||||
#include <torrent/utils/option_strings.h>
|
||||
#include <torrent/utils/log.h>
|
||||
|
||||
#include "command_helpers.h"
|
||||
#include "control.h"
|
||||
#include "core/download.h"
|
||||
#include "core/download_list.h"
|
||||
#include "core/manager.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
#include "rpc/lua.h"
|
||||
#include "rpc/scgi.h"
|
||||
#include "session/session_manager.h"
|
||||
#include "utils/file_status_cache.h"
|
||||
|
||||
#include "globals.h"
|
||||
#include "rpc/lua.h"
|
||||
#include "control.h"
|
||||
#include "command_helpers.h"
|
||||
|
||||
typedef torrent::ChunkManager CM_t;
|
||||
typedef torrent::FileManager FM_t;
|
||||
@@ -44,49 +26,6 @@ apply_pieces_stats_total_size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
system_env(const torrent::Object::string_type& arg) {
|
||||
if (arg.empty())
|
||||
throw torrent::input_error("system.env: Missing variable name.");
|
||||
|
||||
char* val = getenv(arg.c_str());
|
||||
return std::string(val ? val : "");
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
system_hostname() {
|
||||
char buffer[1024];
|
||||
|
||||
if (gethostname(buffer, 1023) == -1)
|
||||
throw torrent::input_error("Unable to read hostname.");
|
||||
|
||||
// if (shorten)
|
||||
// *std::find(buffer, buffer + 1023, '.') = '\0';
|
||||
|
||||
return std::string(buffer);
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
system_get_cwd() {
|
||||
char* buffer = getcwd(NULL, 0);
|
||||
|
||||
if (buffer == NULL)
|
||||
throw torrent::input_error("Unable to read cwd.");
|
||||
|
||||
torrent::Object result = torrent::Object(std::string(buffer));
|
||||
free(buffer);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
system_set_cwd(const torrent::Object::string_type& rawArgs) {
|
||||
if (::chdir(rawArgs.c_str()) != 0)
|
||||
throw torrent::input_error("Could not change current working directory.");
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
inline torrent::Object::list_const_iterator
|
||||
post_increment(torrent::Object::list_const_iterator& itr, const torrent::Object::list_const_iterator& last) {
|
||||
if (itr == last)
|
||||
@@ -186,104 +125,19 @@ cmd_file_append(const torrent::Object::list_type& args) {
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
checked_socket_value(int64_t value, const char* label) {
|
||||
if (value < 0 || value > std::numeric_limits<uint32_t>::max())
|
||||
throw torrent::input_error(std::string("Invalid ") + label + " value.");
|
||||
|
||||
return static_cast<uint32_t>(value);
|
||||
}
|
||||
|
||||
void
|
||||
initialize_command_local() {
|
||||
core::DownloadList* dList = control->core()->download_list();
|
||||
torrent::FileManager* fileManager = torrent::file_manager();
|
||||
|
||||
CMD_ANY ("system.hostname", std::bind(&system_hostname));
|
||||
CMD_ANY ("system.pid", std::bind(&getpid));
|
||||
|
||||
CMD_VAR_C_STRING("system.api_version", (int64_t)API_VERSION);
|
||||
CMD_VAR_C_STRING("system.client_version", PACKAGE_VERSION);
|
||||
CMD_VAR_C_STRING("system.library_version", torrent::runtime::version());
|
||||
|
||||
CMD_VAR_VALUE ("system.file.allocate", 0);
|
||||
CMD_VAR_VALUE ("system.file.max_size", (int64_t)512 << 30);
|
||||
CMD_VAR_VALUE ("system.file.split_size", -1);
|
||||
CMD_VAR_STRING ("system.file.split_suffix", ".part");
|
||||
|
||||
CMD_ANY ("system.file_status_cache.size", std::bind(&utils::FileStatusCache::size,
|
||||
(utils::FileStatusCache::base_type*)control->core()->file_status_cache()));
|
||||
CMD_ANY_V ("system.file_status_cache.prune", std::bind(&utils::FileStatusCache::prune, control->core()->file_status_cache()));
|
||||
|
||||
CMD_VAR_BOOL ("file.prioritize_toc", 0);
|
||||
CMD_VAR_LIST ("file.prioritize_toc.first");
|
||||
CMD_VAR_LIST ("file.prioritize_toc.last");
|
||||
|
||||
CMD_ANY ("system.files.advise_random", std::bind(&FM_t::advise_random, fileManager));
|
||||
CMD_ANY_VALUE_V ("system.files.advise_random.set", std::bind(&FM_t::set_advise_random, fileManager, std::placeholders::_2));
|
||||
CMD_ANY ("system.files.advise_random.hashing", std::bind(&FM_t::advise_random_hashing, fileManager));
|
||||
CMD_ANY_VALUE_V ("system.files.advise_random.hashing.set", std::bind(&FM_t::set_advise_random_hashing, fileManager, std::placeholders::_2));
|
||||
CMD_ANY ("system.files.session.fdatasync", [](auto, auto) { return session_thread::manager()->use_fsyncdisk(); });
|
||||
CMD_ANY_VALUE_V ("system.files.session.fdatasync.set", [](auto, auto& value) { return session_thread::manager()->set_use_fsyncdisk(value); });
|
||||
|
||||
CMD_ANY ("system.files.opened_counter", std::bind(&FM_t::files_opened_counter, fileManager));
|
||||
CMD_ANY ("system.files.closed_counter", std::bind(&FM_t::files_closed_counter, fileManager));
|
||||
CMD_ANY ("system.files.failed_counter", std::bind(&FM_t::files_failed_counter, fileManager));
|
||||
|
||||
CMD_ANY_STRING ("system.env", [](auto, auto& str) { return system_env(str); });
|
||||
|
||||
CMD_ANY ("system.time", [](auto, auto) { return torrent::this_thread::cached_seconds().count(); });
|
||||
CMD_ANY ("system.time_seconds", [](auto, auto) { return torrent::utils::cast_seconds(torrent::utils::time_since_epoch()).count(); });
|
||||
CMD_ANY ("system.time_usec", [](auto, auto) { return torrent::utils::time_since_epoch().count(); });
|
||||
|
||||
CMD_ANY_VALUE_V ("system.umask.set", [](auto, auto& value) { return ::umask(value); });
|
||||
|
||||
CMD_VAR_BOOL ("system.daemon", false);
|
||||
|
||||
CMD_ANY_V ("system.shutdown.normal", [](auto, auto) { control->receive_normal_shutdown(); });
|
||||
CMD_ANY_V ("system.shutdown.quick", [](auto, auto) { control->receive_quick_shutdown(); });
|
||||
|
||||
CMD_REDIRECT_NO_EXPORT("system.shutdown", "system.shutdown.normal");
|
||||
|
||||
CMD_ANY ("system.cwd", [](auto, auto) { return system_get_cwd(); });
|
||||
CMD_ANY_STRING ("system.cwd.set", [](auto, auto& str) { return system_set_cwd(str); });
|
||||
|
||||
CMD_ANY ("system.sockets.size", [](auto, auto) { return torrent::runtime::socket_manager()->size(); });
|
||||
CMD_ANY ("system.sockets.max_size", [](auto, auto) { return torrent::runtime::socket_manager()->max_size(); });
|
||||
CMD_ANY_VALUE_V ("system.sockets.max_size.set", [](auto, auto& value) { return torrent::runtime::socket_manager()->set_max_size_and_adjust(checked_socket_value(value, "socket max size")); });
|
||||
CMD_ANY_V ("system.sockets.adjust_alloc", [](auto, auto) { torrent::runtime::socket_manager()->adjust_allocation(); });
|
||||
CMD_ANY ("system.sockets.reserved_alloc", [](auto, auto) { return torrent::runtime::socket_manager()->reserved_allocation(); });
|
||||
CMD_ANY ("system.sockets.available_alloc", [](auto, auto) { return torrent::runtime::socket_manager()->available_allocation(); });
|
||||
|
||||
for (uint32_t i = 0; i < torrent::runtime::SocketManager::category_count; ++i) {
|
||||
auto category = static_cast<torrent::runtime::socket_manager_category_t>(i);
|
||||
auto category_name = "system.sockets." + torrent::option_to_str_or_throw(torrent::OPTION_SOCKET_CATEGORY, i);
|
||||
|
||||
CMD_ANY (category_name + ".size", [category](auto, auto) { return torrent::runtime::socket_manager()->category_managed_size(category); });
|
||||
CMD_ANY (category_name + ".max_size", [category](auto, auto) { return torrent::runtime::socket_manager()->category_max_size(category); });
|
||||
|
||||
if (i == 0) {
|
||||
CMD_ANY (category_name + ".min_alloc", [](auto, auto) { return torrent::runtime::socket_manager()->generic_min_allocation(); });
|
||||
continue;
|
||||
}
|
||||
|
||||
CMD_ANY (category_name + ".max_alloc.limit", [category](auto, auto) { return torrent::runtime::socket_manager()->category_alloc_limit(category); });
|
||||
CMD_ANY (category_name + ".min_alloc.limit", [category](auto, auto) { return torrent::runtime::socket_manager()->category_alloc_minimum(category); });
|
||||
CMD_ANY (category_name + ".min_alloc", [category](auto, auto) { return torrent::runtime::socket_manager()->category_min_allocation(category); });
|
||||
CMD_ANY (category_name + ".max_alloc", [category](auto, auto) { return torrent::runtime::socket_manager()->category_max_allocation(category); });
|
||||
CMD_ANY_VALUE_V(category_name + ".min_alloc.set", [category](auto, auto& value) { torrent::runtime::socket_manager()->set_category_min_allocation(category, checked_socket_value(value, "socket min alloc")); });
|
||||
CMD_ANY_VALUE_V(category_name + ".max_alloc.set", [category](auto, auto& value) { torrent::runtime::socket_manager()->set_category_max_allocation(category, checked_socket_value(value, "socket max alloc")); });
|
||||
}
|
||||
core::DownloadList* dList = control->core()->download_list();
|
||||
|
||||
CMD_ANY ("pieces.sync.always_safe", [](auto, auto) { return torrent::runtime::memory_manager()->safe_sync(); });
|
||||
CMD_ANY_VALUE_V ("pieces.sync.always_safe.set", [](auto, auto& value) { return torrent::runtime::memory_manager()->set_safe_sync(value); });
|
||||
CMD_ANY ("pieces.sync.safe_free_diskspace", [](auto, auto) { return torrent::runtime::memory_manager()->sync_safe_free_diskspace(); });
|
||||
CMD_ANY ("pieces.sync.timeout", [](auto, auto) { return torrent::runtime::memory_manager()->timeout_sync().count(); });
|
||||
CMD_ANY_VALUE_V ("pieces.sync.timeout.set", [](auto, auto& value) { return torrent::runtime::memory_manager()->set_timeout_sync(value); });
|
||||
// CMD_ANY ("pieces.sync.timeout_safe", [](auto, auto) { return torrent::runtime::memory_manager()->timeout_safe_sync(); });
|
||||
// CMD_ANY_VALUE_V ("pieces.sync.timeout_safe.set", [](auto, auto& value) { return torrent::runtime::memory_manager()->set_timeout_safe_sync(value); });
|
||||
CMD_ANY ("pieces.sync.timeout_safe", [](auto, auto) { return 0; });
|
||||
CMD_ANY_VALUE_V ("pieces.sync.timeout_safe.set", [](auto, auto) { });
|
||||
CMD_ANY_VALUE_V ("pieces.sync.timeout_safe.set", [](auto, auto) {
|
||||
lt_log_print(torrent::LOG_WARN, "pieces.sync.timeout_safe.set is no longer supported and does nothing.");
|
||||
});
|
||||
CMD_ANY ("pieces.sync.queue_size", [](auto, auto) { return torrent::runtime::memory_manager()->sync_queue_block_count(); });
|
||||
|
||||
CMD_ANY ("pieces.preload.type", [](auto, auto) { return torrent::runtime::memory_manager()->preload_type(); });
|
||||
@@ -358,38 +212,6 @@ initialize_command_local() {
|
||||
|
||||
CMD_ANY_LIST ("group.insert", std::bind(&group_insert, std::placeholders::_2));
|
||||
|
||||
rpc::rpc.mark_safe("system.api_version");
|
||||
rpc::rpc.mark_safe("system.client_version");
|
||||
rpc::rpc.mark_safe("system.library_version");
|
||||
rpc::rpc.mark_safe("system.time");
|
||||
rpc::rpc.mark_safe("system.time_seconds");
|
||||
rpc::rpc.mark_safe("system.time_usec");
|
||||
rpc::rpc.mark_safe("system.file.max_size");
|
||||
rpc::rpc.mark_safe("system.file.split_size");
|
||||
rpc::rpc.mark_safe("system.file.split_suffix");
|
||||
|
||||
rpc::rpc.mark_safe("system.sockets.size");
|
||||
rpc::rpc.mark_safe("system.sockets.max_size");
|
||||
rpc::rpc.mark_safe("system.sockets.reserved_alloc");
|
||||
rpc::rpc.mark_safe("system.sockets.available_alloc");
|
||||
|
||||
for (uint32_t i = 0; i < torrent::runtime::SocketManager::category_count; ++i) {
|
||||
auto category_name = "system.sockets." + torrent::option_to_str_or_throw(torrent::OPTION_SOCKET_CATEGORY, i);
|
||||
|
||||
rpc::rpc.mark_safe(category_name + ".size");
|
||||
rpc::rpc.mark_safe(category_name + ".max_size");
|
||||
|
||||
if (i == 0) {
|
||||
rpc::rpc.mark_safe(category_name + ".min_alloc");
|
||||
continue;
|
||||
}
|
||||
|
||||
rpc::rpc.mark_safe(category_name + ".max_alloc.limit");
|
||||
rpc::rpc.mark_safe(category_name + ".min_alloc.limit");
|
||||
rpc::rpc.mark_safe(category_name + ".min_alloc");
|
||||
rpc::rpc.mark_safe(category_name + ".max_alloc");
|
||||
}
|
||||
|
||||
rpc::rpc.mark_safe("directory.default");
|
||||
rpc::rpc.mark_safe("session.path");
|
||||
rpc::rpc.mark_safe("session.path.realpath.or_empty");
|
||||
|
||||
@@ -135,7 +135,7 @@ initialize_command_logging() {
|
||||
CMD2_ANY_LIST ("log.open_gz_file_pid", std::bind(&apply_log_open, log_flag_append_pid | log_flag_use_gz, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.append_file", std::bind(&apply_log_open, log_flag_append_file, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.append_file.flush", std::bind(&apply_log_open, log_flag_append_file | log_flag_flush, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.append_gz_file", std::bind(&apply_log_open, log_flag_append_file, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.append_gz_file", std::bind(&apply_log_open, log_flag_append_file | log_flag_use_gz, std::placeholders::_2));
|
||||
|
||||
CMD2_ANY_STRING_V("log.close", std::bind(&torrent::log_close_output_str, std::placeholders::_2));
|
||||
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <torrent/data/file_manager.h>
|
||||
#include <torrent/runtime/client_config.h>
|
||||
#include <torrent/runtime/memory_manager.h>
|
||||
#include <torrent/runtime/socket_manager.h>
|
||||
#include <torrent/runtime/runtime.h>
|
||||
#include <torrent/utils/chrono.h>
|
||||
#include <torrent/utils/option_strings.h>
|
||||
|
||||
#include "command_helpers.h"
|
||||
#include "control.h"
|
||||
#include "globals.h"
|
||||
#include "core/manager.h"
|
||||
#include "session/session_manager.h"
|
||||
#include "utils/file_status_cache.h"
|
||||
|
||||
|
||||
torrent::Object
|
||||
system_env(const torrent::Object::string_type& arg) {
|
||||
if (arg.empty())
|
||||
throw torrent::input_error("system.env: Missing variable name.");
|
||||
|
||||
char* val = getenv(arg.c_str());
|
||||
return std::string(val ? val : "");
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
system_hostname() {
|
||||
char buffer[1024];
|
||||
|
||||
if (gethostname(buffer, 1023) == -1)
|
||||
throw torrent::input_error("Unable to read hostname.");
|
||||
|
||||
// if (shorten)
|
||||
// *std::find(buffer, buffer + 1023, '.') = '\0';
|
||||
|
||||
return std::string(buffer);
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
system_get_cwd() {
|
||||
char* buffer = getcwd(NULL, 0);
|
||||
|
||||
if (buffer == NULL)
|
||||
throw torrent::input_error("Unable to read cwd.");
|
||||
|
||||
torrent::Object result = torrent::Object(std::string(buffer));
|
||||
free(buffer);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
system_set_cwd(const torrent::Object::string_type& rawArgs) {
|
||||
if (::chdir(rawArgs.c_str()) != 0)
|
||||
throw torrent::input_error("Could not change current working directory.");
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
checked_socket_value(int64_t value, const char* label) {
|
||||
if (value < 0 || value > std::numeric_limits<uint32_t>::max())
|
||||
throw torrent::input_error(std::string("Invalid ") + label + " value.");
|
||||
|
||||
return static_cast<uint32_t>(value);
|
||||
}
|
||||
|
||||
void
|
||||
initialize_command_system() {
|
||||
CMD_ANY ("system.hostname", std::bind(&system_hostname));
|
||||
CMD_ANY ("system.pid", std::bind(&getpid));
|
||||
|
||||
CMD_VAR_C_STRING("system.api_version", (int64_t)API_VERSION);
|
||||
CMD_VAR_C_STRING("system.client_version", PACKAGE_VERSION);
|
||||
CMD_VAR_C_STRING("system.library_version", torrent::runtime::version());
|
||||
|
||||
CMD_ANY ("system.torrent_name.use_sanitized", [](auto, auto) { return torrent::runtime::client_config()->torrent_name_use_sanitized(); });
|
||||
CMD_ANY_VALUE_V ("system.torrent_name.use_sanitized.set", [](auto, auto& value) { return torrent::runtime::client_config()->set_torrent_name_use_sanitized(value); });
|
||||
|
||||
CMD_VAR_VALUE ("system.file.allocate", 0);
|
||||
CMD_VAR_VALUE ("system.file.max_size", (int64_t)512 << 30);
|
||||
CMD_VAR_VALUE ("system.file.split_size", -1);
|
||||
CMD_VAR_STRING ("system.file.split_suffix", ".part");
|
||||
|
||||
CMD_ANY ("system.file_name.replace_slash", [](auto, auto) { return torrent::runtime::client_config()->file_name_replace_slash(); });
|
||||
CMD_ANY_STRING_V("system.file_name.replace_slash.set", [](auto, auto& str) { return torrent::runtime::client_config()->set_file_name_replace_slash(str); });
|
||||
|
||||
CMD_ANY ("system.file_status_cache.size", [](auto, auto) { return control->core()->file_status_cache()->size(); });
|
||||
CMD_ANY_V ("system.file_status_cache.prune", [](auto, auto) { return control->core()->file_status_cache()->prune(); });
|
||||
|
||||
CMD_VAR_BOOL ("file.prioritize_toc", 0);
|
||||
CMD_VAR_LIST ("file.prioritize_toc.first");
|
||||
CMD_VAR_LIST ("file.prioritize_toc.last");
|
||||
|
||||
CMD_ANY ("system.files.advise_random", [](auto, auto) { return torrent::file_manager()->advise_random(); });
|
||||
CMD_ANY_VALUE_V ("system.files.advise_random.set", [](auto, auto& value) { return torrent::file_manager()->set_advise_random(value); });
|
||||
CMD_ANY ("system.files.advise_random.hashing", [](auto, auto) { return torrent::file_manager()->advise_random_hashing(); });
|
||||
CMD_ANY_VALUE_V ("system.files.advise_random.hashing.set", [](auto, auto& value) { return torrent::file_manager()->set_advise_random_hashing(value); });
|
||||
CMD_ANY ("system.files.session.fdatasync", [](auto, auto) { return session_thread::manager()->use_fsyncdisk(); });
|
||||
CMD_ANY_VALUE_V ("system.files.session.fdatasync.set", [](auto, auto& value) { return session_thread::manager()->set_use_fsyncdisk(value); });
|
||||
|
||||
CMD_ANY ("system.files.close_idle", [](auto, auto) { return torrent::file_manager()->close_idle_timeout().count(); });
|
||||
CMD_ANY_VALUE_V ("system.files.close_idle.set", [](auto, auto& value) { return torrent::file_manager()->set_close_idle_timeout(value * 1s); });
|
||||
|
||||
CMD_ANY ("system.files.opened_counter", [](auto, auto) { return torrent::file_manager()->files_opened_counter(); });
|
||||
CMD_ANY ("system.files.closed_counter", [](auto, auto) { return torrent::file_manager()->files_closed_counter(); });
|
||||
CMD_ANY ("system.files.failed_counter", [](auto, auto) { return torrent::file_manager()->files_failed_counter(); });
|
||||
|
||||
CMD_ANY_STRING ("system.env", [](auto, auto& str) { return system_env(str); });
|
||||
|
||||
CMD_ANY ("system.time", [](auto, auto) { return torrent::this_thread::cached_seconds().count(); });
|
||||
CMD_ANY ("system.time_seconds", [](auto, auto) { return torrent::utils::cast_seconds(torrent::utils::time_since_epoch()).count(); });
|
||||
CMD_ANY ("system.time_usec", [](auto, auto) { return torrent::utils::time_since_epoch().count(); });
|
||||
|
||||
CMD_ANY_VALUE_V ("system.umask.set", [](auto, auto& value) { return ::umask(value); });
|
||||
|
||||
CMD_VAR_BOOL ("system.daemon", false);
|
||||
|
||||
CMD_ANY_V ("system.shutdown.normal", [](auto, auto) { control->receive_normal_shutdown(); });
|
||||
CMD_ANY_V ("system.shutdown.quick", [](auto, auto) { control->receive_quick_shutdown(); });
|
||||
|
||||
CMD_REDIRECT_NO_EXPORT("system.shutdown", "system.shutdown.normal");
|
||||
|
||||
CMD_ANY ("system.cwd", [](auto, auto) { return system_get_cwd(); });
|
||||
CMD_ANY_STRING ("system.cwd.set", [](auto, auto& str) { return system_set_cwd(str); });
|
||||
|
||||
CMD_ANY ("system.sockets.size", [](auto, auto) { return torrent::runtime::socket_manager()->size(); });
|
||||
CMD_ANY ("system.sockets.max_size", [](auto, auto) { return torrent::runtime::socket_manager()->max_size(); });
|
||||
CMD_ANY_VALUE_V ("system.sockets.max_size.set", [](auto, auto& value) {
|
||||
return torrent::runtime::socket_manager()->set_max_size_and_adjust(checked_socket_value(value, "socket max size"));
|
||||
});
|
||||
CMD_ANY_V ("system.sockets.adjust_alloc", [](auto, auto) { torrent::runtime::socket_manager()->adjust_allocation(); });
|
||||
CMD_ANY ("system.sockets.reserved_alloc", [](auto, auto) { return torrent::runtime::socket_manager()->reserved_allocation(); });
|
||||
CMD_ANY ("system.sockets.available_alloc", [](auto, auto) { return torrent::runtime::socket_manager()->available_allocation(); });
|
||||
|
||||
for (uint32_t i = 0; i < torrent::runtime::SocketManager::category_count; ++i) {
|
||||
auto category = static_cast<torrent::runtime::socket_manager_category_t>(i);
|
||||
auto category_name = "system.sockets." + torrent::option_to_str_or_throw(torrent::OPTION_SOCKET_CATEGORY, i);
|
||||
|
||||
CMD_ANY (category_name + ".size", [category](auto, auto) { return torrent::runtime::socket_manager()->category_managed_size(category); });
|
||||
CMD_ANY (category_name + ".max_size", [category](auto, auto) { return torrent::runtime::socket_manager()->category_max_size(category); });
|
||||
|
||||
if (i == 0) {
|
||||
CMD_ANY (category_name + ".min_alloc", [](auto, auto) { return torrent::runtime::socket_manager()->generic_min_allocation(); });
|
||||
continue;
|
||||
}
|
||||
|
||||
CMD_ANY (category_name + ".max_alloc.limit", [category](auto, auto) { return torrent::runtime::socket_manager()->category_alloc_limit(category); });
|
||||
CMD_ANY (category_name + ".min_alloc.limit", [category](auto, auto) { return torrent::runtime::socket_manager()->category_alloc_minimum(category); });
|
||||
CMD_ANY (category_name + ".min_alloc", [category](auto, auto) { return torrent::runtime::socket_manager()->category_min_allocation(category); });
|
||||
CMD_ANY (category_name + ".max_alloc", [category](auto, auto) { return torrent::runtime::socket_manager()->category_max_allocation(category); });
|
||||
CMD_ANY_VALUE_V(category_name + ".min_alloc.set", [category](auto, auto& value) {
|
||||
torrent::runtime::socket_manager()->set_category_min_allocation(category, checked_socket_value(value, "socket min alloc"));
|
||||
});
|
||||
CMD_ANY_VALUE_V(category_name + ".max_alloc.set", [category](auto, auto& value) {
|
||||
torrent::runtime::socket_manager()->set_category_max_allocation(category, checked_socket_value(value, "socket max alloc"));
|
||||
});
|
||||
}
|
||||
|
||||
rpc::rpc.mark_safe("system.api_version");
|
||||
rpc::rpc.mark_safe("system.client_version");
|
||||
rpc::rpc.mark_safe("system.library_version");
|
||||
rpc::rpc.mark_safe("system.time");
|
||||
rpc::rpc.mark_safe("system.time_seconds");
|
||||
rpc::rpc.mark_safe("system.time_usec");
|
||||
rpc::rpc.mark_safe("system.file.max_size");
|
||||
rpc::rpc.mark_safe("system.file.split_size");
|
||||
rpc::rpc.mark_safe("system.file.split_suffix");
|
||||
|
||||
rpc::rpc.mark_safe("system.sockets.size");
|
||||
rpc::rpc.mark_safe("system.sockets.max_size");
|
||||
rpc::rpc.mark_safe("system.sockets.reserved_alloc");
|
||||
rpc::rpc.mark_safe("system.sockets.available_alloc");
|
||||
|
||||
for (uint32_t i = 0; i < torrent::runtime::SocketManager::category_count; ++i) {
|
||||
auto category_name = "system.sockets." + torrent::option_to_str_or_throw(torrent::OPTION_SOCKET_CATEGORY, i);
|
||||
|
||||
rpc::rpc.mark_safe(category_name + ".size");
|
||||
rpc::rpc.mark_safe(category_name + ".max_size");
|
||||
|
||||
if (i == 0) {
|
||||
rpc::rpc.mark_safe(category_name + ".min_alloc");
|
||||
continue;
|
||||
}
|
||||
|
||||
rpc::rpc.mark_safe(category_name + ".max_alloc.limit");
|
||||
rpc::rpc.mark_safe(category_name + ".min_alloc.limit");
|
||||
rpc::rpc.mark_safe(category_name + ".min_alloc");
|
||||
rpc::rpc.mark_safe(category_name + ".max_alloc");
|
||||
}
|
||||
}
|
||||
@@ -118,4 +118,6 @@ private:
|
||||
std::atomic<bool> m_shutdown_quick{};
|
||||
};
|
||||
|
||||
extern Control* control;
|
||||
|
||||
#endif
|
||||
|
||||
+13
-3
@@ -101,7 +101,18 @@ Download::set_throttle_name(const std::string& name) {
|
||||
}
|
||||
|
||||
void
|
||||
Download::set_root_directory(const std::string& path) {
|
||||
Download::set_directory(const std::string& path) {
|
||||
if (!m_download.file_list()->is_multi_file())
|
||||
return set_base_directory(path);
|
||||
|
||||
if (path.empty() || *path.rbegin() == '/')
|
||||
return set_base_directory(path + m_download.info()->name_sanitized());
|
||||
|
||||
set_base_directory(path + "/" + m_download.info()->name_sanitized());
|
||||
}
|
||||
|
||||
void
|
||||
Download::set_base_directory(const std::string& path) {
|
||||
// If the download is open, hashed and has completed chunks make
|
||||
// sure to verify that the download files are still present.
|
||||
//
|
||||
@@ -120,13 +131,12 @@ Download::set_root_directory(const std::string& path) {
|
||||
!file_stat.update(file_list->front()->frozen_path().str()))) {
|
||||
|
||||
set_message("Cannot change the directory of an open download after the files have been moved.");
|
||||
rpc::call_command("d.state.set", (int64_t)0, rpc::make_target(this));
|
||||
control->core()->download_list()->close_directly(this);
|
||||
|
||||
throw torrent::input_error("Cannot change the directory of an open download after the files have been moved.");
|
||||
}
|
||||
|
||||
control->core()->download_list()->close_directly(this);
|
||||
control->core()->download_list()->close_files(this);
|
||||
file_list->set_root_dir(expand_path(path));
|
||||
|
||||
bencode()->get_key("rtorrent").insert_key("directory", path);
|
||||
|
||||
+2
-1
@@ -79,7 +79,8 @@ public:
|
||||
uint32_t resume_flags() { return m_resumeFlags; }
|
||||
void set_resume_flags(uint32_t flags) { m_resumeFlags = flags; }
|
||||
|
||||
void set_root_directory(const std::string& path);
|
||||
void set_directory(const std::string& path);
|
||||
void set_base_directory(const std::string& path);
|
||||
|
||||
void set_throttle_name(const std::string& name);
|
||||
|
||||
|
||||
+210
-77
@@ -27,6 +27,8 @@
|
||||
|
||||
namespace core {
|
||||
|
||||
static constexpr const char* session_invalid_message = "Session data is invalid, ignoring it";
|
||||
|
||||
bool
|
||||
is_network_uri(const std::string& uri) {
|
||||
return
|
||||
@@ -35,9 +37,15 @@ is_network_uri(const std::string& uri) {
|
||||
std::strncmp(uri.c_str(), "ftp://", 6) == 0;
|
||||
}
|
||||
|
||||
static constexpr const char* session_invalid_message = "Session data is invalid, ignoring it";
|
||||
bool
|
||||
is_magnet_uri(const std::string& uri) {
|
||||
return
|
||||
std::strncmp(uri.c_str(), "magnet:?", 8) == 0;
|
||||
}
|
||||
|
||||
static std::unique_ptr<torrent::Object>
|
||||
namespace {
|
||||
|
||||
std::unique_ptr<torrent::Object>
|
||||
download_factory_load_stream(const char* filename, bool* is_invalid) {
|
||||
std::fstream stream(filename, std::ios::in | std::ios::binary);
|
||||
|
||||
@@ -55,17 +63,34 @@ download_factory_load_stream(const char* filename, bool* is_invalid) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
bool
|
||||
is_magnet_uri(const std::string& uri) {
|
||||
return
|
||||
std::strncmp(uri.c_str(), "magnet:?", 8) == 0;
|
||||
std::unique_ptr<torrent::Object>
|
||||
create_untrusted_object(torrent::Object& obj) {
|
||||
auto trusted_object = std::make_unique<torrent::Object>(torrent::Object::create_map());
|
||||
|
||||
if (obj.has_key("info"))
|
||||
trusted_object->insert_key_move("info", obj.get_key("info"));
|
||||
|
||||
if (obj.has_key("announce"))
|
||||
trusted_object->insert_key_move("announce", obj.get_key("announce"));
|
||||
|
||||
if (obj.has_key("announce-list"))
|
||||
trusted_object->insert_key_move("announce-list", obj.get_key("announce-list"));
|
||||
|
||||
if (obj.has_key("creation date"))
|
||||
trusted_object->insert_key_move("creation date", obj.get_key("creation date"));
|
||||
|
||||
if (obj.has_key("created by"))
|
||||
trusted_object->insert_key_move("created by", obj.get_key("created by"));
|
||||
|
||||
return trusted_object;
|
||||
}
|
||||
|
||||
DownloadFactory::DownloadFactory(Manager* m) :
|
||||
m_manager(m) {
|
||||
} // namespace anonymous
|
||||
|
||||
m_task_load.slot() = std::bind(&DownloadFactory::receive_load, this);
|
||||
m_task_commit.slot() = std::bind(&DownloadFactory::receive_commit, this);
|
||||
|
||||
DownloadFactory::DownloadFactory(Manager* m, bool trusted)
|
||||
: m_manager(m),
|
||||
m_trusted(trusted) {
|
||||
|
||||
// m_variables["connection_leech"] = rpc::call_command("protocol.connection.leech");
|
||||
// m_variables["connection_seed"] = rpc::call_command("protocol.connection.seed");
|
||||
@@ -78,21 +103,49 @@ DownloadFactory::DownloadFactory(Manager* m) :
|
||||
DownloadFactory::~DownloadFactory() {
|
||||
torrent::this_thread::scheduler()->erase(&m_task_load);
|
||||
torrent::this_thread::scheduler()->erase(&m_task_commit);
|
||||
|
||||
delete m_object;
|
||||
}
|
||||
|
||||
void
|
||||
DownloadFactory::load(const std::string& uri) {
|
||||
DownloadFactory::load_trusted(const std::string& uri) {
|
||||
if (!m_trusted)
|
||||
throw torrent::internal_error("DownloadFactory::load_trusted() called on an untrusted object");
|
||||
|
||||
m_uri = uri;
|
||||
m_task_load.slot() = [this]() { receive_load_trusted(); };
|
||||
|
||||
torrent::this_thread::scheduler()->wait_for(&m_task_load, 0ms);
|
||||
}
|
||||
|
||||
// This function must be called before DownloadFactory::commit().
|
||||
void
|
||||
DownloadFactory::load_raw_data(const std::string& input) {
|
||||
DownloadFactory::load_untrusted(const std::string& uri) {
|
||||
if (m_trusted)
|
||||
throw torrent::internal_error("DownloadFactory::load_untrusted() called on a trusted object");
|
||||
|
||||
m_uri = uri;
|
||||
m_task_load.slot() = [this]() { receive_load_untrusted(); };
|
||||
|
||||
torrent::this_thread::scheduler()->wait_for(&m_task_load, 0ms);
|
||||
}
|
||||
|
||||
void
|
||||
DownloadFactory::load_raw_data_trusted(const std::string& input) {
|
||||
if (!m_trusted)
|
||||
throw torrent::internal_error("DownloadFactory::load_raw_data_trusted() called on an untrusted object");
|
||||
|
||||
if (m_stream)
|
||||
throw torrent::internal_error("DownloadFactory::load*() called on an object with m_stream != NULL");
|
||||
throw torrent::internal_error("DownloadFactory::load_raw_data_trusted() called on an object with m_stream != NULL");
|
||||
|
||||
m_stream.reset(new std::stringstream(input));
|
||||
m_loaded = true;
|
||||
}
|
||||
|
||||
void
|
||||
DownloadFactory::load_raw_data_untrusted(const std::string& input) {
|
||||
if (m_trusted)
|
||||
throw torrent::internal_error("DownloadFactory::load_raw_data_untrusted() called on an trusted object");
|
||||
|
||||
if (m_stream)
|
||||
throw torrent::internal_error("DownloadFactory::load_raw_data_untrusted() called on an object with m_stream != NULL");
|
||||
|
||||
m_stream.reset(new std::stringstream(input));
|
||||
m_loaded = true;
|
||||
@@ -100,53 +153,91 @@ DownloadFactory::load_raw_data(const std::string& input) {
|
||||
|
||||
void
|
||||
DownloadFactory::commit() {
|
||||
if (!m_trusted)
|
||||
throw torrent::internal_error("DownloadFactory::commit() called on an untrusted object");
|
||||
|
||||
m_task_commit.slot() = [this]() { receive_commit(); };
|
||||
torrent::this_thread::scheduler()->wait_for(&m_task_commit, 0ms);
|
||||
}
|
||||
|
||||
void
|
||||
DownloadFactory::receive_load() {
|
||||
if (m_stream)
|
||||
throw torrent::internal_error("DownloadFactory::load*() called on an object with m_stream != NULL");
|
||||
DownloadFactory::process_load_network_uri() {
|
||||
m_stream.reset(new std::stringstream);
|
||||
|
||||
if (is_network_uri(m_uri)) {
|
||||
m_stream.reset(new std::stringstream);
|
||||
// TODO: Add trusted flag.
|
||||
|
||||
auto done_fn = [this]() { receive_loaded(); };
|
||||
auto failed_fn = [this](const std::string& error) { receive_failed(error); };
|
||||
auto done_fn = [this]() { receive_loaded(); };
|
||||
auto failed_fn = [this](const std::string& error) { receive_failed(error); };
|
||||
|
||||
m_manager->http_queue()->insert(m_uri, m_stream, done_fn, failed_fn);
|
||||
m_manager->http_queue()->insert(m_uri, m_stream, done_fn, failed_fn);
|
||||
|
||||
m_variables["tied_to_file"] = (int64_t)false;
|
||||
return;
|
||||
}
|
||||
m_variables["tied_to_file"] = (int64_t)false;
|
||||
}
|
||||
|
||||
if (is_magnet_uri(m_uri)) {
|
||||
// DEBUG: Use m_object.
|
||||
m_stream.reset(new std::stringstream());
|
||||
*m_stream << "d10:magnet-uri" << m_uri.length() << ":" << m_uri << "e";
|
||||
void
|
||||
DownloadFactory::process_load_magnet_uri() {
|
||||
m_stream.reset(new std::stringstream());
|
||||
*m_stream << "d10:magnet-uri" << m_uri.length() << ":" << m_uri << "e";
|
||||
|
||||
m_variables["tied_to_file"] = (int64_t)false;
|
||||
m_variables["tied_to_file"] = (int64_t)false;
|
||||
|
||||
receive_loaded();
|
||||
return;
|
||||
}
|
||||
receive_loaded();
|
||||
}
|
||||
|
||||
void
|
||||
DownloadFactory::process_load_file_uri() {
|
||||
std::fstream stream(expand_path(m_uri).c_str(), std::ios::in | std::ios::binary);
|
||||
|
||||
if (!stream.is_open())
|
||||
return receive_failed("Could not open file");
|
||||
|
||||
m_object = new torrent::Object;
|
||||
m_object = std::make_unique<torrent::Object>();
|
||||
stream >> *m_object;
|
||||
|
||||
if (!stream.good())
|
||||
return receive_failed("Reading torrent file failed");
|
||||
|
||||
m_isFile = true;
|
||||
m_is_file = true;
|
||||
|
||||
receive_loaded();
|
||||
}
|
||||
|
||||
void
|
||||
DownloadFactory::receive_load_trusted() {
|
||||
if (!m_trusted)
|
||||
throw torrent::internal_error("DownloadFactory::receive_load_trusted() called on an untrusted object");
|
||||
|
||||
if (m_stream)
|
||||
throw torrent::internal_error("DownloadFactory::receive_load_trusted() called on an object with null m_stream");
|
||||
|
||||
if (is_network_uri(m_uri))
|
||||
return process_load_network_uri();
|
||||
|
||||
if (is_magnet_uri(m_uri))
|
||||
return process_load_magnet_uri();
|
||||
|
||||
process_load_file_uri();
|
||||
}
|
||||
|
||||
void
|
||||
DownloadFactory::receive_load_untrusted() {
|
||||
if (m_trusted)
|
||||
throw torrent::internal_error("DownloadFactory::receive_load_untrusted() called on a trusted object");
|
||||
|
||||
if (m_stream)
|
||||
throw torrent::internal_error("DownloadFactory::load*() called on an object with null m_stream");
|
||||
|
||||
if (is_network_uri(m_uri))
|
||||
return process_load_network_uri();
|
||||
|
||||
// TODO: Don't need to handle untrusted commands magnet URIs.
|
||||
|
||||
// if (is_magnet_uri(m_uri))
|
||||
// return process_load_magnet_uri();
|
||||
|
||||
throw torrent::internal_error("DownloadFactory::receive_load_untrusted() called on a non-network/magnet URI");
|
||||
}
|
||||
|
||||
void
|
||||
DownloadFactory::receive_loaded() {
|
||||
m_loaded = true;
|
||||
@@ -165,30 +256,40 @@ DownloadFactory::receive_commit() {
|
||||
|
||||
void
|
||||
DownloadFactory::receive_success() {
|
||||
bool session_invalid = false;
|
||||
if (!m_trusted && m_session)
|
||||
throw torrent::internal_error("DownloadFactory::receive_success() called on an untrusted object with m_session == true");
|
||||
|
||||
auto rtorrent_object = download_factory_load_stream((expand_path(m_uri) + ".rtorrent").c_str(), &session_invalid);
|
||||
auto libtorrent_resume_object = download_factory_load_stream((expand_path(m_uri) + ".libtorrent_resume").c_str(), &session_invalid);
|
||||
if (m_session && !m_is_file)
|
||||
throw torrent::internal_error("DownloadFactory::receive_success() called on a non-file object with m_session == true");
|
||||
|
||||
if (session_invalid)
|
||||
lt_log_print(torrent::LOG_ERROR, "%s: %s", session_invalid_message, m_uri.c_str());
|
||||
bool session_invalid = false;
|
||||
uint32_t tracker_key = tracker_key = random() % (std::numeric_limits<uint32_t>::max() - 1) + 1;
|
||||
|
||||
uint32_t tracker_key;
|
||||
std::unique_ptr<torrent::Object> rtorrent_object, libtorrent_resume_object;
|
||||
|
||||
if (rtorrent_object && rtorrent_object->has_key_value("key"))
|
||||
tracker_key = rtorrent_object->get_key_value("key");
|
||||
else
|
||||
tracker_key = random() % (std::numeric_limits<uint32_t>::max() - 1) + 1;
|
||||
if (m_session) {
|
||||
rtorrent_object = download_factory_load_stream((expand_path(m_uri) + ".rtorrent").c_str(), &session_invalid);
|
||||
libtorrent_resume_object = download_factory_load_stream((expand_path(m_uri) + ".libtorrent_resume").c_str(), &session_invalid);
|
||||
|
||||
Download* download = m_stream != nullptr ?
|
||||
m_manager->download_list()->create(m_stream.get(), tracker_key, m_printLog) :
|
||||
m_manager->download_list()->create(m_object, tracker_key, m_printLog);
|
||||
if (session_invalid)
|
||||
lt_log_print(torrent::LOG_ERROR, "%s: %s", session_invalid_message, m_uri.c_str());
|
||||
|
||||
m_object = NULL;
|
||||
if (rtorrent_object && rtorrent_object->has_key_value("key"))
|
||||
tracker_key = rtorrent_object->get_key_value("key");
|
||||
}
|
||||
|
||||
if (download == NULL) {
|
||||
// core::Manager should already have added the error message to
|
||||
// the log.
|
||||
// TODO: This adds the torrent, so untrusted can add brokent torrents.
|
||||
|
||||
if (m_stream != nullptr)
|
||||
object_from_stream();
|
||||
|
||||
if (m_trusted)
|
||||
m_object = create_untrusted_object(*m_object);
|
||||
|
||||
Download* download = m_manager->download_list()->create(std::move(m_object), tracker_key, m_print_log);
|
||||
|
||||
if (download == nullptr) {
|
||||
// core::Manager should already have added the error message to the log.
|
||||
m_slot_finished();
|
||||
return;
|
||||
}
|
||||
@@ -197,39 +298,49 @@ DownloadFactory::receive_success() {
|
||||
download->set_hash_failed(true);
|
||||
download->set_message(session_invalid_message);
|
||||
|
||||
if (m_printLog)
|
||||
if (m_print_log)
|
||||
m_manager->push_log_std(std::string(session_invalid_message) + ": \"" + m_uri + "\"");
|
||||
}
|
||||
|
||||
torrent::Object* root = download->bencode();
|
||||
|
||||
if (download->download()->info()->is_meta_download()) {
|
||||
if (!m_trusted)
|
||||
throw torrent::internal_error("DownloadFactory::receive_success() called on an untrusted object with a meta download");
|
||||
|
||||
torrent::Object& meta = root->insert_key("rtorrent_meta_download", torrent::Object::create_map());
|
||||
meta.insert_key("start", m_start);
|
||||
meta.insert_key("print_log", m_printLog);
|
||||
meta.insert_key("print_log", m_print_log);
|
||||
|
||||
torrent::Object::list_type& commands = meta.insert_key("commands", torrent::Object::create_list()).as_list();
|
||||
// TODO: ADD UNTRUSTED!!!
|
||||
auto& commands = meta.insert_key("commands", torrent::Object::create_list()).as_list();
|
||||
|
||||
for (auto& m_command : m_commands)
|
||||
commands.push_back(m_command);
|
||||
}
|
||||
|
||||
if (m_session) {
|
||||
if (!m_trusted)
|
||||
throw torrent::internal_error("DownloadFactory::receive_success() called on an untrusted object with m_session == true");
|
||||
|
||||
if (rtorrent_object)
|
||||
root->insert_key_move("rtorrent", *rtorrent_object);
|
||||
|
||||
if (libtorrent_resume_object)
|
||||
root->insert_key_move("libtorrent_resume", *libtorrent_resume_object);
|
||||
|
||||
} else if (!m_trusted) {
|
||||
if (root->has_key("rtorrent") || root->has_key("libtorrent_resume"))
|
||||
throw torrent::internal_error("DownloadFactory::receive_success() called on an untrusted object with 'rtorrent' or 'libtorrent_resume' keys");
|
||||
|
||||
} else {
|
||||
// We only allow session torrents to keep their
|
||||
// 'rtorrent/libtorrent' sections. The "fast_resume" section
|
||||
// should be safe to keep.
|
||||
// We only allow session torrents to keep their 'rtorrent/libtorrent' sections. The
|
||||
// "fast_resume" section should be safe to keep.
|
||||
root->erase_key("rtorrent");
|
||||
}
|
||||
|
||||
torrent::Object* rtorrent = &root->insert_preserve_copy("rtorrent", torrent::Object::create_map()).first->second;
|
||||
torrent::Object& resumeObject = root->insert_preserve_copy("libtorrent_resume", torrent::Object::create_map()).first->second;
|
||||
auto* rtorrent = &root->insert_preserve_copy("rtorrent", torrent::Object::create_map()).first->second;
|
||||
auto& resumeObject = root->insert_preserve_copy("libtorrent_resume", torrent::Object::create_map()).first->second;
|
||||
|
||||
rtorrent->insert_key("key", download->tracker_controller().key());
|
||||
|
||||
@@ -259,7 +370,7 @@ DownloadFactory::receive_success() {
|
||||
}
|
||||
|
||||
// Skip forcing trackers to scrape when rtorrent starts
|
||||
if (m_initLoad && rpc::call_command_value("trackers.delay_scrape"))
|
||||
if (m_init_load && rpc::call_command_value("trackers.delay_scrape"))
|
||||
download->set_resume_flags(torrent::Download::start_skip_tracker);
|
||||
|
||||
// Check first if we already have these values set in the session
|
||||
@@ -301,7 +412,7 @@ DownloadFactory::receive_success() {
|
||||
|
||||
lt_log_print(torrent::LOG_ERROR, "%s: %s", msg.c_str(), m_uri.c_str());
|
||||
|
||||
if (m_printLog)
|
||||
if (m_print_log)
|
||||
m_manager->push_log_std(msg + ": \"" + m_uri + "\"");
|
||||
|
||||
download->set_hash_failed(true);
|
||||
@@ -325,8 +436,13 @@ DownloadFactory::receive_success() {
|
||||
if (torrent::log_groups[torrent::LOG_TORRENT_DEBUG].valid())
|
||||
log_created(download, rtorrent);
|
||||
|
||||
for (const auto& command : m_commands)
|
||||
rpc::parse_command_multiple_std(command, rpc::make_target(download));
|
||||
if (m_trusted) {
|
||||
for (const auto& command : m_commands)
|
||||
rpc::parse_command_multiple_std(command, rpc::make_target(download));
|
||||
|
||||
} else {
|
||||
// TODO: CALL UNTRUSTED COMMANDS
|
||||
}
|
||||
|
||||
if (m_manager->download_list()->find(infohash) == m_manager->download_list()->end())
|
||||
throw torrent::input_error("The newly created download was removed.");
|
||||
@@ -340,7 +456,7 @@ DownloadFactory::receive_success() {
|
||||
} catch (torrent::input_error& e) {
|
||||
std::string msg = "Command on torrent creation failed: " + std::string(e.what());
|
||||
|
||||
if (m_printLog)
|
||||
if (m_print_log)
|
||||
m_manager->push_log_std(msg);
|
||||
|
||||
if (m_manager->download_list()->find(infohash) != m_manager->download_list()->end()) {
|
||||
@@ -354,6 +470,18 @@ DownloadFactory::receive_success() {
|
||||
m_slot_finished();
|
||||
}
|
||||
|
||||
void
|
||||
DownloadFactory::receive_failed(const std::string& msg) {
|
||||
if (m_print_log) {
|
||||
if (m_trusted)
|
||||
m_manager->push_log_std("Failed to load torrent: " + msg + ": \"" + m_uri + "\"");
|
||||
else
|
||||
m_manager->push_log_std("Failed to load untrusted torrent: " + msg);
|
||||
}
|
||||
|
||||
m_slot_finished();
|
||||
}
|
||||
|
||||
void
|
||||
DownloadFactory::log_created(Download* download, torrent::Object* rtorrent) {
|
||||
std::stringstream dump;
|
||||
@@ -380,15 +508,6 @@ DownloadFactory::log_created(Download* download, torrent::Object* rtorrent) {
|
||||
lt_log_print_dump(torrent::LOG_TORRENT_DEBUG, dump_str.c_str(), dump_str.size(), "Creating new download:");
|
||||
}
|
||||
|
||||
void
|
||||
DownloadFactory::receive_failed(const std::string& msg) {
|
||||
// Add message to log.
|
||||
if (m_printLog)
|
||||
m_manager->push_log_std(msg + ": \"" + m_uri + "\"");
|
||||
|
||||
m_slot_finished();
|
||||
}
|
||||
|
||||
void
|
||||
DownloadFactory::initialize_rtorrent(Download* download, torrent::Object* rtorrent) {
|
||||
auto cached_seconds = torrent::this_thread::cached_seconds().count();
|
||||
@@ -412,7 +531,7 @@ DownloadFactory::initialize_rtorrent(Download* download, torrent::Object* rtorre
|
||||
rtorrent->insert_preserve_copy("timestamp.finished", (int64_t)0);
|
||||
|
||||
rtorrent->insert_preserve_copy("tied_to_file", "");
|
||||
rtorrent->insert_key("loaded_file", m_isFile ? m_uri : std::string());
|
||||
rtorrent->insert_key("loaded_file", m_is_file ? m_uri : std::string());
|
||||
|
||||
if (rtorrent->has_key_value("priority"))
|
||||
rpc::call_command("d.priority.set", rtorrent->get_key_value("priority") % 4, rpc::make_target(download));
|
||||
@@ -444,4 +563,18 @@ DownloadFactory::initialize_rtorrent(Download* download, torrent::Object* rtorre
|
||||
rtorrent->insert_preserve_copy("choke_heuristics.down.seed", std::string());
|
||||
}
|
||||
|
||||
void
|
||||
DownloadFactory::object_from_stream() {
|
||||
m_object = std::make_unique<torrent::Object>();
|
||||
|
||||
*m_stream >> *m_object;
|
||||
|
||||
if (!m_stream->good() || !m_object->is_map()) {
|
||||
if (m_print_log)
|
||||
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not create download, stream is not a valid torrent.");
|
||||
|
||||
throw torrent::input_error("Invalid torrent data");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+27
-14
@@ -24,14 +24,18 @@ public:
|
||||
typedef std::vector<std::string> command_list_type;
|
||||
|
||||
// Do not destroy this object while it is in a HttpQueue.
|
||||
DownloadFactory(Manager* m);
|
||||
DownloadFactory(Manager* m, bool trusted);
|
||||
~DownloadFactory();
|
||||
|
||||
// Calling of receive_load() is delayed so you can change whatever
|
||||
// you want without fear of the slots being triggered as you call
|
||||
// load() or commit().
|
||||
void load(const std::string& uri);
|
||||
void load_raw_data(const std::string& input);
|
||||
void load_trusted(const std::string& uri);
|
||||
void load_untrusted(const std::string& uri);
|
||||
|
||||
void load_raw_data_trusted(const std::string& input);
|
||||
void load_raw_data_untrusted(const std::string& input);
|
||||
|
||||
void commit();
|
||||
|
||||
command_list_type& commands() { return m_commands; }
|
||||
@@ -43,16 +47,21 @@ public:
|
||||
bool get_start() const { return m_start; }
|
||||
void set_start(bool v) { m_start = v; }
|
||||
|
||||
bool get_init_load() const { return m_initLoad; }
|
||||
void set_init_load(bool v) { m_initLoad = v; }
|
||||
bool get_init_load() const { return m_init_load; }
|
||||
void set_init_load(bool v) { m_init_load = v; }
|
||||
|
||||
bool print_log() const { return m_printLog; }
|
||||
void set_print_log(bool v) { m_printLog = v; }
|
||||
bool print_log() const { return m_print_log; }
|
||||
void set_print_log(bool v) { m_print_log = v; }
|
||||
|
||||
void slot_finished(slot_void s) { m_slot_finished = s; }
|
||||
|
||||
private:
|
||||
void receive_load();
|
||||
void process_load_network_uri();
|
||||
void process_load_magnet_uri();
|
||||
void process_load_file_uri();
|
||||
|
||||
void receive_load_trusted();
|
||||
void receive_load_untrusted();
|
||||
void receive_loaded();
|
||||
void receive_commit();
|
||||
void receive_success();
|
||||
@@ -62,19 +71,23 @@ private:
|
||||
|
||||
void initialize_rtorrent(Download* download, torrent::Object* rtorrent);
|
||||
|
||||
Manager* m_manager;
|
||||
std::shared_ptr<std::iostream> m_stream;
|
||||
torrent::Object* m_object{};
|
||||
void object_from_stream();
|
||||
|
||||
Manager* m_manager;
|
||||
|
||||
std::shared_ptr<std::iostream> m_stream;
|
||||
std::unique_ptr<torrent::Object> m_object{};
|
||||
|
||||
bool m_trusted{};
|
||||
bool m_commited{};
|
||||
bool m_loaded{};
|
||||
|
||||
std::string m_uri;
|
||||
bool m_session{};
|
||||
bool m_start{};
|
||||
bool m_printLog{true};
|
||||
bool m_isFile{};
|
||||
bool m_initLoad{};
|
||||
bool m_print_log{true};
|
||||
bool m_is_file{};
|
||||
bool m_init_load{};
|
||||
|
||||
command_list_type m_commands;
|
||||
torrent::Object::map_type m_variables;
|
||||
|
||||
+49
-49
@@ -101,49 +101,17 @@ DownloadList::find_hex_ptr(const char* hash) {
|
||||
}
|
||||
|
||||
Download*
|
||||
DownloadList::create(torrent::Object* obj, uint32_t tracker_key, bool printLog) {
|
||||
DownloadList::create(std::unique_ptr<torrent::Object> obj, uint32_t tracker_key, bool printLog) {
|
||||
torrent::Download download;
|
||||
|
||||
try {
|
||||
download = torrent::download_add(obj, tracker_key);
|
||||
|
||||
} catch (torrent::local_error& e) {
|
||||
if (printLog)
|
||||
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not create download: %s", e.what());
|
||||
|
||||
delete obj;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// There's no non-critical exceptions that should be throwable by
|
||||
// the ctor, so don't catch.
|
||||
return new Download(download);
|
||||
}
|
||||
|
||||
Download*
|
||||
DownloadList::create(std::istream* str, uint32_t tracker_key, bool printLog) {
|
||||
torrent::Object* object = new torrent::Object;
|
||||
torrent::Download download;
|
||||
auto obj_ptr = obj.get();
|
||||
|
||||
try {
|
||||
*str >> *object;
|
||||
|
||||
// Don't throw input_error from here as gcc-3.3.5 produces bad
|
||||
// code.
|
||||
if (str->fail()) {
|
||||
delete object;
|
||||
|
||||
if (printLog)
|
||||
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not create download, the input is not a valid torrent.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
download = torrent::download_add(object, tracker_key);
|
||||
download = torrent::download_add(obj.release(), tracker_key);
|
||||
|
||||
} catch (torrent::local_error& e) {
|
||||
delete object;
|
||||
// TODO: Fix download_add so it takes the unique_ptr.
|
||||
delete obj_ptr;
|
||||
|
||||
if (printLog)
|
||||
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not create download: %s", e.what());
|
||||
@@ -254,9 +222,11 @@ DownloadList::close(Download* download) {
|
||||
}
|
||||
}
|
||||
|
||||
// Releases the files without changing the download's state, for callers that
|
||||
// need the files closed and will keep using the download.
|
||||
void
|
||||
DownloadList::close_directly(Download* download) {
|
||||
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Closing download directly.");
|
||||
DownloadList::close_files(Download* download) {
|
||||
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Closing download files.");
|
||||
|
||||
if (download->download()->info()->is_active()) {
|
||||
download->download()->stop(torrent::Download::stop_skip_tracker);
|
||||
@@ -269,6 +239,44 @@ DownloadList::close_directly(Download* download) {
|
||||
download->download()->close();
|
||||
}
|
||||
|
||||
void
|
||||
DownloadList::close_directly(Download* download) {
|
||||
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Closing download directly.");
|
||||
|
||||
bool was_active = download->download()->info()->is_active();
|
||||
bool was_open = download->download()->info()->is_open();
|
||||
|
||||
close_files(download);
|
||||
set_state_stopped(download);
|
||||
|
||||
if (was_active) {
|
||||
DL_TRIGGER_EVENT(download, "event.download.paused");
|
||||
update_paused_state(download);
|
||||
}
|
||||
|
||||
if (was_open) {
|
||||
DL_TRIGGER_EVENT(download, "event.download.hash_removed");
|
||||
DL_TRIGGER_EVENT(download, "event.download.closed");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DownloadList::set_state_stopped(Download* download) {
|
||||
control->view_manager()->find_ptr_throw("stopped")->set_visible(download);
|
||||
rpc::call_command("d.state.set", (int64_t)0, rpc::make_target(download));
|
||||
}
|
||||
|
||||
void
|
||||
DownloadList::update_paused_state(Download* download) {
|
||||
rpc::call_command("d.state_changed.set", torrent::this_thread::cached_seconds().count(), rpc::make_target(download));
|
||||
rpc::call_command("d.state_counter.set", rpc::call_command_value("d.state_counter", rpc::make_target(download)), rpc::make_target(download));
|
||||
|
||||
// If initial seeding is complete, don't try it again when restarting.
|
||||
if (download->is_done() &&
|
||||
rpc::call_command("d.connection_current", torrent::Object(), rpc::make_target(download)).as_string() == "initial_seed")
|
||||
rpc::call_command("d.connection_seed.set", rpc::call_command("d.connection_current", torrent::Object(), rpc::make_target(download)), rpc::make_target(download));
|
||||
}
|
||||
|
||||
void
|
||||
DownloadList::close_quick(Download* download) {
|
||||
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Closing download quickly.");
|
||||
@@ -443,15 +451,7 @@ DownloadList::pause(Download* download, int flags) {
|
||||
// view.
|
||||
DL_TRIGGER_EVENT(download, "event.download.paused");
|
||||
|
||||
auto cached_seconds = torrent::this_thread::cached_seconds().count();
|
||||
|
||||
rpc::call_command("d.state_changed.set", cached_seconds, rpc::make_target(download));
|
||||
rpc::call_command("d.state_counter.set", rpc::call_command_value("d.state_counter", rpc::make_target(download)), rpc::make_target(download));
|
||||
|
||||
// If initial seeding is complete, don't try it again when restarting.
|
||||
if (download->is_done() &&
|
||||
rpc::call_command("d.connection_current", torrent::Object(), rpc::make_target(download)).as_string() == "initial_seed")
|
||||
rpc::call_command("d.connection_seed.set", rpc::call_command("d.connection_current", torrent::Object(), rpc::make_target(download)), rpc::make_target(download));
|
||||
update_paused_state(download);
|
||||
|
||||
// Save the state after all the slots, etc have been called so we
|
||||
// include the modifications they may make.
|
||||
@@ -522,7 +522,7 @@ DownloadList::hash_done(Download* download) {
|
||||
// If the download was previously completed but the files were
|
||||
// f.ex deleted, then we clear the state and complete.
|
||||
if (rpc::call_command_value("d.complete", rpc::make_target(download)) && !download->is_done()) {
|
||||
rpc::call_command("d.state.set", (int64_t)0, rpc::make_target(download));
|
||||
set_state_stopped(download);
|
||||
download->set_message("Download registered as completed, but hash check returned unfinished chunks.");
|
||||
}
|
||||
|
||||
|
||||
@@ -52,8 +52,7 @@ public:
|
||||
Download* find_hex_ptr(const char* hash);
|
||||
|
||||
// Might move this to DownloadFactory.
|
||||
Download* create(std::istream* str, uint32_t tracker_key, bool printLog);
|
||||
Download* create(torrent::Object* obj, uint32_t tracker_key, bool printLog);
|
||||
Download* create(std::unique_ptr<torrent::Object> obj, uint32_t tracker_key, bool printLog);
|
||||
|
||||
iterator insert(Download* d);
|
||||
|
||||
@@ -75,6 +74,7 @@ public:
|
||||
|
||||
void close(Download* d);
|
||||
void close_directly(Download* d);
|
||||
void close_files(Download* d);
|
||||
void close_quick(Download* d);
|
||||
void close_throw(Download* d);
|
||||
|
||||
@@ -132,6 +132,9 @@ private:
|
||||
void hash_done(Download* d);
|
||||
void hash_queue(Download* d, int type);
|
||||
|
||||
void set_state_stopped(Download* d);
|
||||
void update_paused_state(Download* d);
|
||||
|
||||
inline void check_contains(Download* d);
|
||||
|
||||
void received_finished(Download* d);
|
||||
|
||||
+75
-32
@@ -37,6 +37,8 @@
|
||||
|
||||
namespace core {
|
||||
|
||||
void path_expand(std::vector<std::string>* paths, const std::string& pattern);
|
||||
|
||||
const int Manager::create_start;
|
||||
const int Manager::create_tied;
|
||||
const int Manager::create_quiet;
|
||||
@@ -195,7 +197,7 @@ Manager::try_create_download(const std::string& uri, int flags, const command_li
|
||||
return;
|
||||
|
||||
// Adding download.
|
||||
DownloadFactory* f = new DownloadFactory(this);
|
||||
DownloadFactory* f = new DownloadFactory(this, true);
|
||||
|
||||
f->variables()["tied_to_file"] = (int64_t)(bool)(flags & create_tied);
|
||||
f->commands().insert(f->commands().end(), commands.begin(), commands.end());
|
||||
@@ -204,29 +206,52 @@ Manager::try_create_download(const std::string& uri, int flags, const command_li
|
||||
f->set_print_log(!(flags & create_quiet));
|
||||
f->slot_finished([f]() { delete f; });
|
||||
|
||||
if (is_data_uri(uri)) {
|
||||
if (flags & create_raw_data) {
|
||||
f->load_raw_data_trusted(uri);
|
||||
|
||||
} else if (is_data_uri(uri)) {
|
||||
// Allow the use of data URIs, primarily for JSON-RPC which
|
||||
// doesn't have a defined mechanism for binary data
|
||||
f->load_raw_data(decode_data_uri(uri));
|
||||
f->load_raw_data_trusted(decode_data_uri(uri));
|
||||
f->variables()["tied_to_file"] = (int64_t)false;
|
||||
} else if (flags & create_raw_data) {
|
||||
f->load_raw_data(uri);
|
||||
|
||||
} else {
|
||||
f->load(uri);
|
||||
f->load_trusted(uri);
|
||||
}
|
||||
|
||||
f->commit();
|
||||
}
|
||||
|
||||
void
|
||||
Manager::try_create_download_expand(const std::string& uri, int flags, command_list_type commands) {
|
||||
if (flags & create_raw_data) {
|
||||
try_create_download(uri, flags, commands);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> paths;
|
||||
paths.reserve(256);
|
||||
|
||||
path_expand(&paths, uri);
|
||||
|
||||
if (!paths.empty())
|
||||
for (auto& path : paths)
|
||||
try_create_download(path, flags, commands);
|
||||
|
||||
else
|
||||
try_create_download(uri, flags, commands);
|
||||
}
|
||||
|
||||
void
|
||||
Manager::try_create_download_from_meta_download(torrent::Object* bencode, const std::string& metafile) {
|
||||
DownloadFactory* f = new DownloadFactory(this);
|
||||
DownloadFactory* f = new DownloadFactory(this, true);
|
||||
|
||||
f->variables()["tied_to_file"] = (int64_t)true;
|
||||
f->variables()["tied_file"] = metafile;
|
||||
f->variables()["tied_file"] = metafile;
|
||||
|
||||
torrent::Object& meta = bencode->get_key("rtorrent_meta_download");
|
||||
torrent::Object::list_type& commands = meta.get_key_list("commands");
|
||||
|
||||
for (const auto& command : commands)
|
||||
f->commands().insert(f->commands().end(), command.as_string());
|
||||
|
||||
@@ -239,13 +264,46 @@ Manager::try_create_download_from_meta_download(torrent::Object* bencode, const
|
||||
std::stringstream s;
|
||||
s.imbue(std::locale::classic());
|
||||
s << *bencode;
|
||||
f->load_raw_data(s.str());
|
||||
|
||||
f->load_raw_data_trusted(s.str());
|
||||
f->commit();
|
||||
}
|
||||
|
||||
utils::Directory
|
||||
path_expand_transform(std::string path, const utils::directory_entry& entry) {
|
||||
return path + entry.s_name;
|
||||
void
|
||||
Manager::try_create_download_untrusted(const std::string& uri, int flags, const command_list_type& commands) {
|
||||
// TODO: Need to check if we are allowed, also rate limit.
|
||||
|
||||
if (!(flags & create_raw_data) &&
|
||||
!is_network_uri(uri) &&
|
||||
!is_magnet_uri(uri) &&
|
||||
!is_data_uri(uri)) {
|
||||
push_log_std("URI type not allowed for untrusted loads.");
|
||||
return;
|
||||
}
|
||||
|
||||
DownloadFactory* f = new DownloadFactory(this, false);
|
||||
|
||||
f->commands().insert(f->commands().end(), commands.begin(), commands.end());
|
||||
|
||||
f->set_start(flags & create_start);
|
||||
f->set_print_log(!(flags & create_quiet));
|
||||
f->slot_finished([f]() { delete f; });
|
||||
|
||||
if (flags & create_raw_data) {
|
||||
f->load_raw_data_untrusted(uri);
|
||||
|
||||
} else if (is_data_uri(uri)) {
|
||||
// Allow the use of data URIs, primarily for JSON-RPC which
|
||||
// doesn't have a defined mechanism for binary data
|
||||
f->load_raw_data_untrusted(decode_data_uri(uri));
|
||||
f->variables()["tied_to_file"] = (int64_t)false;
|
||||
|
||||
} else {
|
||||
// f->load_untrusted(uri);
|
||||
throw torrent::internal_error("Manager::try_create_download_untrusted() unimplemented.");
|
||||
}
|
||||
|
||||
f->commit();
|
||||
}
|
||||
|
||||
namespace {
|
||||
@@ -304,6 +362,11 @@ split_iterator(const Sequence&) {
|
||||
|
||||
}
|
||||
|
||||
utils::Directory
|
||||
path_expand_transform(std::string path, const utils::directory_entry& entry) {
|
||||
return path + entry.s_name;
|
||||
}
|
||||
|
||||
// Move this somewhere better.
|
||||
void
|
||||
path_expand(std::vector<std::string>* paths, const std::string& pattern) {
|
||||
@@ -360,26 +423,6 @@ manager_equal_tied(const std::string& path, Download* download) {
|
||||
return path == rpc::call_command_string("d.tied_to_file", rpc::make_target(download));
|
||||
}
|
||||
|
||||
void
|
||||
Manager::try_create_download_expand(const std::string& uri, int flags, command_list_type commands) {
|
||||
if (flags & create_raw_data) {
|
||||
try_create_download(uri, flags, commands);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> paths;
|
||||
paths.reserve(256);
|
||||
|
||||
path_expand(&paths, uri);
|
||||
|
||||
if (!paths.empty())
|
||||
for (auto& path : paths)
|
||||
try_create_download(path, flags, commands);
|
||||
|
||||
else
|
||||
try_create_download(uri, flags, commands);
|
||||
}
|
||||
|
||||
// DownloadList's hashing related functions don't actually start the
|
||||
// hashing, it only reacts to events. This functions checks the
|
||||
// hashing view and starts hashing if nessesary.
|
||||
|
||||
@@ -78,6 +78,8 @@ public:
|
||||
void try_create_download_expand(const std::string& uri, int flags, command_list_type commands = command_list_type());
|
||||
void try_create_download_from_meta_download(torrent::Object* bencode, const std::string& metafile);
|
||||
|
||||
void try_create_download_untrusted(const std::string& uri, int flags, const command_list_type& commands);
|
||||
|
||||
private:
|
||||
void create_http(const std::string& uri);
|
||||
void create_final(std::istream* s);
|
||||
|
||||
@@ -379,6 +379,12 @@ main(int argc, char** argv) {
|
||||
lt_log_print(torrent::LOG_WARN, "network.max_open_files.set is deprecated, use system.sockets.files.min_alloc.set instead.");
|
||||
});
|
||||
|
||||
// TODO: Keep d.directory_base for a while as it is widely used.
|
||||
CMD_REDIRECT("d.directory_base", "d.directory");
|
||||
CMD_REDIRECT("d.directory_base.set", "d.directory.base.set");
|
||||
|
||||
rpc::rpc.mark_safe("d.directory_base");
|
||||
|
||||
// if (rpc::call_command_value("method.use_intermediate") == 1) {
|
||||
|
||||
// } else if (rpc::call_command_value("method.use_intermediate") == 2) {
|
||||
|
||||
@@ -167,6 +167,14 @@ RpcManager::cleanup() {
|
||||
m_jsonrpc.cleanup();
|
||||
}
|
||||
|
||||
void
|
||||
RpcManager::set_size_limit(uint64_t size) {
|
||||
if (size > SCgiTask::max_content_size)
|
||||
throw torrent::input_error("XMLRPC size limit cannot exceed the SCGI content size limit.");
|
||||
|
||||
m_xmlrpc.set_size_limit(size);
|
||||
}
|
||||
|
||||
void
|
||||
RpcManager::insert_command(const char* name, const char* parm, const char* doc) {
|
||||
m_xmlrpc.insert_command(name, parm, doc);
|
||||
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
void cleanup();
|
||||
|
||||
int64_t size_limit() { return m_xmlrpc.size_limit(); };
|
||||
void set_size_limit(uint64_t size) { m_xmlrpc.set_size_limit(size); };
|
||||
void set_size_limit(uint64_t size);
|
||||
|
||||
int dialect() { return m_xmlrpc.dialect(); }
|
||||
void set_dialect(int dialect) { m_xmlrpc.set_dialect(dialect); }
|
||||
|
||||
@@ -529,9 +529,6 @@ XmlRpc::size_limit() {
|
||||
|
||||
void
|
||||
XmlRpc::set_size_limit(uint64_t size) {
|
||||
if (size >= (64 << 20))
|
||||
throw torrent::input_error("Invalid XMLRPC limit size.");
|
||||
|
||||
xmlrpc_limit_set(XMLRPC_XML_SIZE_LIMIT_ID, size);
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ private:
|
||||
|
||||
inline bool SessionManager::is_used() const { return !m_path.empty(); }
|
||||
inline std::string SessionManager::path() const { return m_path; }
|
||||
inline bool SessionManager::use_fsyncdisk() const { return true; }
|
||||
inline bool SessionManager::use_fsyncdisk() const { return m_use_fsyncdisk; }
|
||||
inline bool SessionManager::use_lock() const { return m_use_lock; }
|
||||
inline void SessionManager::flush_all_pending_builds() { process_pending_builds(true); }
|
||||
|
||||
|
||||
+4
-4
@@ -157,12 +157,12 @@ load_session_torrents(const std::string& path) {
|
||||
if (!entry.is_file())
|
||||
continue;
|
||||
|
||||
auto* f = new core::DownloadFactory(control->core());
|
||||
auto* f = new core::DownloadFactory(control->core(), true);
|
||||
|
||||
f->set_session(true);
|
||||
f->set_init_load(true);
|
||||
f->slot_finished([f](){ delete f; });
|
||||
f->load(entries.path() + entry.s_name);
|
||||
f->load_trusted(entries.path() + entry.s_name);
|
||||
f->commit();
|
||||
}
|
||||
}
|
||||
@@ -170,12 +170,12 @@ load_session_torrents(const std::string& path) {
|
||||
void
|
||||
load_arg_torrents(char** first, char** last) {
|
||||
for (; first != last; ++first) {
|
||||
auto* f = new core::DownloadFactory(control->core());
|
||||
auto* f = new core::DownloadFactory(control->core(), true);
|
||||
|
||||
f->set_start(true);
|
||||
f->set_init_load(true);
|
||||
f->slot_finished([f](){ delete f; });
|
||||
f->load(*first);
|
||||
f->load_trusted(*first);
|
||||
f->commit();
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -51,8 +51,8 @@ rtorrent_Test_Rpc_SOURCES = $(rtorrent_Test_Common) \
|
||||
rtorrent_Test_Src_SOURCES = $(rtorrent_Test_Common) \
|
||||
src/test_command_dynamic.cc \
|
||||
src/test_command_dynamic.h \
|
||||
src/test_command_local.cc \
|
||||
src/test_command_local.h \
|
||||
src/test_command_system.cc \
|
||||
src/test_command_system.h \
|
||||
src/test_command_path.cc \
|
||||
src/test_command_path.h \
|
||||
src/test_command_string.cc \
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "test/src/test_command_local.h"
|
||||
#include "test/src/test_command_system.h"
|
||||
|
||||
#include <torrent/torrent.h>
|
||||
#include <torrent/runtime/socket_manager.h>
|
||||
@@ -10,12 +10,12 @@
|
||||
#include "globals.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(TestCommandLocal);
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(TestCommandSystem);
|
||||
|
||||
void initialize_command_local();
|
||||
void initialize_command_system();
|
||||
|
||||
void
|
||||
TestCommandLocal::setUp() {
|
||||
TestCommandSystem::setUp() {
|
||||
torrent::initialize_main_thread();
|
||||
torrent::initialize();
|
||||
|
||||
@@ -23,16 +23,16 @@ TestCommandLocal::setUp() {
|
||||
control = new Control;
|
||||
|
||||
if (!rpc::commands.has("system.sockets.size"))
|
||||
initialize_command_local();
|
||||
initialize_command_system();
|
||||
}
|
||||
|
||||
void
|
||||
TestCommandLocal::tearDown() {
|
||||
TestCommandSystem::tearDown() {
|
||||
torrent::cleanup();
|
||||
}
|
||||
|
||||
void
|
||||
TestCommandLocal::test_socket_category_commands() {
|
||||
TestCommandSystem::test_socket_category_commands() {
|
||||
for (uint32_t i = 0; i < torrent::runtime::SocketManager::category_count; ++i) {
|
||||
auto category = static_cast<torrent::runtime::socket_manager_category_t>(i);
|
||||
auto name = "system.sockets." + torrent::option_to_str_or_throw(torrent::OPTION_SOCKET_CATEGORY, i);
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "test/helpers/test_fixture.h"
|
||||
|
||||
class TestCommandLocal : public test_fixture {
|
||||
CPPUNIT_TEST_SUITE(TestCommandLocal);
|
||||
class TestCommandSystem : public test_fixture {
|
||||
CPPUNIT_TEST_SUITE(TestCommandSystem);
|
||||
|
||||
CPPUNIT_TEST(test_socket_category_commands);
|
||||
|
||||
Reference in New Issue
Block a user