From 19be810642c3f36bf2f0377467ac9120c06e6ab4 Mon Sep 17 00:00:00 2001 From: rakshasa Date: Mon, 15 Mar 2010 16:42:05 +0000 Subject: [PATCH] * Added '-D' flag which turns of redirects for deprecated commands. Use this to ensure your scripts/webui. * Moved DownloadInfo to src/torrent. * Applied the magnet-uri patch. git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@1144 e378c898-3ddf-0310-93e7-cc216c733640 --- src/command_download.cc | 15 ++++++----- src/command_helpers.h | 6 +++++ src/core/dht_manager.cc | 2 +- src/core/download.cc | 2 +- src/core/download.h | 9 ++++--- src/core/download_factory.cc | 29 ++++++++++++++++++-- src/core/download_factory.h | 1 + src/core/download_list.cc | 52 +++++++++++++++++++++++++++++++----- src/core/download_list.h | 2 ++ src/core/manager.cc | 28 +++++++++++++++++++ src/core/manager.h | 1 + src/display/utils.cc | 6 ++--- src/main.cc | 7 +++++ src/ui/download.cc | 2 +- 14 files changed, 138 insertions(+), 24 deletions(-) diff --git a/src/command_download.cc b/src/command_download.cc index de221c63..8f25cbc8 100644 --- a/src/command_download.cc +++ b/src/command_download.cc @@ -336,7 +336,7 @@ apply_d_add_peer(core::Download* download, const std::string& arg) { char dummy; char host[1024]; - if (download->download()->is_private()) + if (download->download()->info()->is_private()) throw torrent::input_error("Download is private."); ret = std::sscanf(arg.c_str(), "%1023[^:]:%i%c", host, &port, &dummy); @@ -600,13 +600,13 @@ initialize_command_download() { ADD_CD_STRING("add_peer", std::ptr_fun(&apply_d_add_peer)); - ADD_CD_VALUE("is_open", rak::on(std::mem_fun(&core::Download::download), std::mem_fun(&torrent::Download::is_open))); - ADD_CD_VALUE("is_active", rak::on(std::mem_fun(&core::Download::download), std::mem_fun(&torrent::Download::is_active))); + ADD_CD_VALUE("is_open", rak::on(std::mem_fun(&core::Download::info), std::mem_fun(&torrent::DownloadInfo::is_open))); + ADD_CD_VALUE("is_active", rak::on(std::mem_fun(&core::Download::info), std::mem_fun(&torrent::DownloadInfo::is_active))); ADD_CD_VALUE("is_hash_checked", rak::on(std::mem_fun(&core::Download::download), std::mem_fun(&torrent::Download::is_hash_checked))); ADD_CD_VALUE("is_hash_checking", rak::on(std::mem_fun(&core::Download::download), std::mem_fun(&torrent::Download::is_hash_checking))); ADD_CD_VALUE("is_multi_file", rak::on(std::mem_fun(&core::Download::file_list), std::mem_fun(&torrent::FileList::is_multi_file))); - ADD_CD_VALUE("is_private", rak::on(std::mem_fun(&core::Download::download), std::mem_fun(&torrent::Download::is_private))); - ADD_CD_VALUE("is_pex_active", rak::on(std::mem_fun(&core::Download::download), std::mem_fun(&torrent::Download::is_pex_active))); + ADD_CD_VALUE("is_private", rak::on(std::mem_fun(&core::Download::info), std::mem_fun(&torrent::DownloadInfo::is_private))); + ADD_CD_VALUE("is_pex_active", rak::on(std::mem_fun(&core::Download::info), std::mem_fun(&torrent::DownloadInfo::is_pex_active))); ADD_CD_VARIABLE_STRING_PUBLIC("custom1", "rtorrent", "custom1"); ADD_CD_VARIABLE_STRING_PUBLIC("custom2", "rtorrent", "custom2"); @@ -676,8 +676,6 @@ initialize_command_download() { ADD_CD_VALUE_UNI("peers_complete", rak::on(std::mem_fun(&core::Download::download), std::mem_fun(&torrent::Download::peers_complete))); ADD_CD_VALUE_UNI("peers_accounted", rak::on(std::mem_fun(&core::Download::download), std::mem_fun(&torrent::Download::peers_accounted))); - ADD_CD_VALUE_MEM_BI("peer_exchange", &core::Download::download, &torrent::Download::set_pex_enabled, &torrent::Download::is_pex_enabled); - ADD_CD_VALUE_MEM_UNI("up_rate", &torrent::Download::mutable_up_rate, &torrent::Rate::rate); ADD_CD_VALUE_MEM_UNI("up_total", &torrent::Download::mutable_up_rate, &torrent::Rate::total); ADD_CD_VALUE_MEM_UNI("down_rate", &torrent::Download::mutable_down_rate, &torrent::Rate::rate); @@ -722,4 +720,7 @@ initialize_command_download() { // NEWISH: CMD_D_VOID("d.initialize_logs", &cmd_d_initialize_logs); + + CMD_D_VOID_SLOT("d.peer_exchange", rak::on(std::mem_fun(&core::Download::info), std::mem_fun(&torrent::DownloadInfo::is_pex_enabled))); + CMD_D_VALUE_SLOT("d.peer_exchange.set", rak::on2(std::mem_fun(&core::Download::download), std::mem_fun(&torrent::Download::set_pex_enabled))); } diff --git a/src/command_helpers.h b/src/command_helpers.h index bc0ae14b..0c7cdfdb 100644 --- a/src/command_helpers.h +++ b/src/command_helpers.h @@ -225,6 +225,12 @@ add_variable(key, NULL, NULL, &rpc::CommandVariable::get_string, NULL, std::stri #define CMD_D_VOID(key, slot) \ CMD_D_SLOT(key, call_unknown, rpc::object_fn(slot), "i:", "") +#define CMD_D_VOID_SLOT(key, slot) \ + CMD_D_SLOT(key, call_unknown, rpc::object_void_fn(slot), "i:", "") + +#define CMD_D_VALUE_SLOT(key, slot) \ + CMD_D_SLOT(key, call_value, rpc::object_value_fn(slot), "i:i", "") + #define CMD_FUNC_SINGLE(key, command) \ rpc::commands.insert_type(key, new rpc::CommandFunction(command), &rpc::CommandFunction::call, rpc::CommandMap::flag_public_xmlrpc, NULL, NULL); diff --git a/src/core/dht_manager.cc b/src/core/dht_manager.cc index 93a717c2..5dc09b92 100644 --- a/src/core/dht_manager.cc +++ b/src/core/dht_manager.cc @@ -194,7 +194,7 @@ DhtManager::update() { DownloadList::const_iterator itr, end; for (itr = control->core()->download_list()->begin(), end = control->core()->download_list()->end(); itr != end; ++itr) - if ((*itr)->is_active() && !(*itr)->download()->is_private()) + if ((*itr)->download()->info()->is_active() && !(*itr)->download()->info()->is_private()) break; if (itr == end) { diff --git a/src/core/download.cc b/src/core/download.cc index 244f6400..e50a98d9 100644 --- a/src/core/download.cc +++ b/src/core/download.cc @@ -159,7 +159,7 @@ Download::receive_chunk_failed(__UNUSED uint32_t idx) { void Download::set_throttle_name(const std::string& throttleName) { - if (m_download.is_active()) + if (m_download.info()->is_active()) throw torrent::input_error("Cannot set throttle on active download."); torrent::ThrottlePair throttles = control->core()->get_throttle(throttleName); diff --git a/src/core/download.h b/src/core/download.h index 235c5b6f..030dad2e 100644 --- a/src/core/download.h +++ b/src/core/download.h @@ -39,6 +39,7 @@ #include #include +#include #include #include #include @@ -70,8 +71,10 @@ public: Download(download_type d); ~Download(); - bool is_open() const { return m_download.is_open(); } - bool is_active() const { return m_download.is_active(); } + const torrent::DownloadInfo* info() const { return m_download.info(); } + + bool is_open() const { return m_download.info()->is_open(); } + bool is_active() const { return m_download.info()->is_active(); } bool is_done() const { return m_download.file_list()->is_done(); } bool is_downloading() const { return is_active() && !is_done(); } bool is_seeding() const { return is_active() && is_done(); } @@ -79,7 +82,7 @@ public: // FIXME: Fixed a bug in libtorrent that caused is_hash_checked to // return true when the torrent is closed. Remove this redundant // test in the next milestone. - bool is_hash_checked() const { return m_download.is_open() && m_download.is_hash_checked(); } + bool is_hash_checked() const { return is_open() && m_download.is_hash_checked(); } bool is_hash_checking() const { return m_download.is_hash_checking(); } bool is_hash_failed() const { return m_hashFailed; } diff --git a/src/core/download_factory.cc b/src/core/download_factory.cc index fef67f0e..4f34560c 100644 --- a/src/core/download_factory.cc +++ b/src/core/download_factory.cc @@ -87,6 +87,12 @@ download_factory_add_stream(torrent::Object* root, const char* key, const char* return true; } +bool +is_magnet_uri(const std::string& uri) { + return + std::strncmp(uri.c_str(), "magnet:?", 8) == 0; +} + DownloadFactory::DownloadFactory(Manager* m) : m_manager(m), m_stream(NULL), @@ -153,6 +159,14 @@ DownloadFactory::receive_load() { m_variables["tied_to_file"] = (int64_t)false; + } else if (is_magnet_uri(m_uri)) { + // DEBUG: Use m_object. + m_stream = new std::stringstream(); + *m_stream << "d10:magnet-uri" << m_uri.length() << ":" << m_uri << "e"; + + m_variables["tied_to_file"] = (int64_t)false; + receive_loaded(); + } else { std::fstream stream(rak::path_expand(m_uri).c_str(), std::ios::in | std::ios::binary); @@ -204,6 +218,17 @@ DownloadFactory::receive_success() { torrent::Object* root = download->bencode(); + if (download->download()->info()->is_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); + + torrent::Object::list_type& commands = meta.insert_key("commands", torrent::Object::create_list()).as_list(); + + for (command_list_type::iterator itr = m_commands.begin(); itr != m_commands.end(); ++itr) + commands.push_back(*itr); + } + if (m_session) { download_factory_add_stream(root, "rtorrent", (rak::path_expand(m_uri) + ".rtorrent").c_str()); download_factory_add_stream(root, "libtorrent_resume", (rak::path_expand(m_uri) + ".libtorrent_resume").c_str()); @@ -260,9 +285,9 @@ DownloadFactory::receive_success() { rpc::call_command("d.set_directory_base", rtorrent->get_key("directory"), rpc::make_target(download)); if (!m_session && m_variables["tied_to_file"].as_value()) - rpc::call_command("d.set_tied_to_file", m_uri, rpc::make_target(download)); + rpc::call_command("d.set_tied_to_file", m_uri.empty() ? m_variables["tied_file"] : m_uri, rpc::make_target(download)); - rpc::call_command("d.set_peer_exchange", rpc::call_command_value("get_peer_exchange"), rpc::make_target(download)); + rpc::call_command("d.peer_exchange.set", rpc::call_command_value("get_peer_exchange"), rpc::make_target(download)); torrent::resume_load_addresses(*download->download(), resumeObject); torrent::resume_load_file_priorities(*download->download(), resumeObject); diff --git a/src/core/download_factory.h b/src/core/download_factory.h index 4b8549d0..7bd7fc47 100644 --- a/src/core/download_factory.h +++ b/src/core/download_factory.h @@ -113,6 +113,7 @@ private: }; bool is_network_uri(const std::string& uri); +bool is_magnet_uri(const std::string& uri); } diff --git a/src/core/download_list.cc b/src/core/download_list.cc index e8b48b7c..e7372db7 100644 --- a/src/core/download_list.cc +++ b/src/core/download_list.cc @@ -37,10 +37,12 @@ #include "config.h" #include +#include #include #include #include #include +#include #include #include #include @@ -236,7 +238,7 @@ void DownloadList::open_throw(Download* download) { check_contains(download); - if (download->download()->is_open()) + if (download->download()->info()->is_open()) return; int openFlags = download->resume_flags(); @@ -261,14 +263,14 @@ DownloadList::close(Download* download) { void DownloadList::close_directly(Download* download) { - if (download->download()->is_active()) { + if (download->download()->info()->is_active()) { download->download()->stop(torrent::Download::stop_skip_tracker); if (torrent::resume_check_target_files(*download->download(), download->download()->bencode()->get_key("libtorrent_resume"))) torrent::resume_save_progress(*download->download(), download->download()->bencode()->get_key("libtorrent_resume")); } - if (download->download()->is_open()) + if (download->download()->info()->is_open()) download->download()->close(); } @@ -320,7 +322,7 @@ DownloadList::resume(Download* download, int flags) { try { - if (download->download()->is_active()) + if (download->download()->info()->is_active()) return; rpc::parse_command_single(rpc::make_target(download), "view.set_visible=active"); @@ -369,7 +371,7 @@ DownloadList::resume(Download* download, int flags) { } // If the DHT server is set to auto, start it now. - if (!download->download()->is_private()) + if (!download->download()->info()->is_private()) control->dht_manager()->auto_start(); // Update the priority to ensure it has the correct @@ -405,7 +407,7 @@ DownloadList::pause(Download* download, int flags) { rpc::commands.call_catch("event.download.hash_removed", rpc::make_target(download), torrent::Object(), "Download event action failed: "); } - if (!download->download()->is_active()) + if (!download->download()->info()->is_active()) return; download->download()->stop(flags); @@ -475,6 +477,9 @@ DownloadList::hash_done(Download* download) { int64_t hashing = rpc::call_command_value("d.get_hashing", rpc::make_target(download)); rpc::call_command_set_value("d.set_hashing", Download::variable_hashing_stopped, rpc::make_target(download)); + if (download->is_done() && download->download()->info()->is_meta_download()) + return process_meta_download(download); + switch (hashing) { case Download::variable_hashing_initial: case Download::variable_hashing_rehash: @@ -566,6 +571,9 @@ void DownloadList::confirm_finished(Download* download) { check_contains(download); + if (download->download()->info()->is_meta_download()) + return process_meta_download(download); + rpc::call_command("d.set_complete", (int64_t)1, rpc::make_target(download)); rpc::call_command("d.set_connection_current", rpc::call_command_void("d.get_connection_seed", rpc::make_target(download)), rpc::make_target(download)); @@ -599,4 +607,36 @@ DownloadList::confirm_finished(Download* download) { resume(download, torrent::Download::start_no_create | torrent::Download::start_skip_tracker | torrent::Download::start_keep_baseline); } +void +DownloadList::process_meta_download(Download* download) { + rpc::call_command("d.stop", torrent::Object(), rpc::make_target(download)); + rpc::call_command("d.close", torrent::Object(), rpc::make_target(download)); + + std::string metafile = (*download->file_list()->begin())->frozen_path(); + std::fstream file(metafile.c_str(), std::ios::in | std::ios::binary); + if (!file.is_open()) { + control->core()->push_log("Could not read download metadata."); + return; + } + + torrent::Object* bencode = new torrent::Object(torrent::Object::create_map()); + file >> bencode->insert_key("info", torrent::Object()); + if (file.fail()) { + delete bencode; + control->core()->push_log("Could not create download, the input is not a valid torrent."); + return; + } + file.close(); + + // Steal the keys we still need. The old download has no use for them. + bencode->insert_key("rtorrent_meta_download", torrent::Object()).swap(download->bencode()->get_key("rtorrent_meta_download")); + if (download->bencode()->has_key("announce")) + bencode->insert_key("announce", torrent::Object()).swap(download->bencode()->get_key("announce")); + if (download->bencode()->has_key("announce-list")) + bencode->insert_key("announce-list", torrent::Object()).swap(download->bencode()->get_key("announce-list")); + + erase_ptr(download); + control->core()->try_create_download_from_meta_download(bencode, metafile); +} + } diff --git a/src/core/download_list.h b/src/core/download_list.h index b52c8808..d4ffb921 100644 --- a/src/core/download_list.h +++ b/src/core/download_list.h @@ -162,6 +162,8 @@ private: void received_finished(Download* d); void confirm_finished(Download* d); + + void process_meta_download(Download* d); }; } diff --git a/src/core/manager.cc b/src/core/manager.cc index e5eecb2a..de32817f 100644 --- a/src/core/manager.cc +++ b/src/core/manager.cc @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -395,6 +397,7 @@ Manager::try_create_download(const std::string& uri, int flags, const command_li if ((flags & create_tied) && !(flags & create_raw_data) && !is_network_uri(uri) && + !is_magnet_uri(uri) && !file_status_cache()->insert(uri, 0)) return; @@ -416,6 +419,31 @@ Manager::try_create_download(const std::string& uri, int flags, const command_li f->commit(); } +void +Manager::try_create_download_from_meta_download(torrent::Object* bencode, const std::string& metafile) { + DownloadFactory* f = new DownloadFactory(this); + + f->variables()["tied_to_file"] = (int64_t)true; + 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 (torrent::Object::list_type::const_iterator itr = commands.begin(); itr != commands.end(); ++itr) + f->commands().insert(f->commands().end(), itr->as_string()); + + f->set_start(meta.get_key_value("start")); + f->set_print_log(meta.get_key_value("print_log")); + f->slot_finished(sigc::bind(sigc::ptr_fun(&rak::call_delete_func), f)); + + // Bit of a waste to create the bencode repesentation here + // only to have the DownloadFactory decode it. + std::stringstream s; + s.imbue(std::locale::classic()); + s << *bencode; + f->load_raw_data(s.str()); + f->commit(); +} + utils::Directory path_expand_transform(std::string path, const utils::directory_entry& entry) { return path + entry.d_name; diff --git a/src/core/manager.h b/src/core/manager.h index 3b23da3e..16902af3 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -128,6 +128,7 @@ public: // Temporary, find a better place for this. void try_create_download(const std::string& uri, int flags, const command_list_type& commands); 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); private: typedef RangeMap AddressThrottleMap; diff --git a/src/display/utils.cc b/src/display/utils.cc index d2f1af47..f5d1c635 100644 --- a/src/display/utils.cc +++ b/src/display/utils.cc @@ -132,9 +132,9 @@ print_download_title(char* first, char* last, core::Download* d) { char* print_download_info(char* first, char* last, core::Download* d) { - if (!d->download()->is_open()) + if (!d->download()->info()->is_open()) first = print_buffer(first, last, "[CLOSED] "); - else if (!d->download()->is_active()) + else if (!d->download()->info()->is_active()) first = print_buffer(first, last, "[OPEN] "); else first = print_buffer(first, last, " "); @@ -151,7 +151,7 @@ print_download_info(char* first, char* last, core::Download* d) { (double)d->download()->down_rate()->rate() / (1 << 10), (double)d->download()->up_rate()->total() / (1 << 20)); - if (d->download()->is_active() && !d->is_done()) { + if (d->download()->info()->is_active() && !d->is_done()) { first = print_buffer(first, last, " "); first = print_download_percentage_done(first, last, d); diff --git a/src/main.cc b/src/main.cc index 7c27bf59..81ebbc13 100644 --- a/src/main.cc +++ b/src/main.cc @@ -86,6 +86,7 @@ parse_options(Control* c, int argc, char** argv) { // Converted. optionParser.insert_flag('h', sigc::ptr_fun(&print_help)); optionParser.insert_flag('n', OptionParser::Slot()); + optionParser.insert_flag('D', OptionParser::Slot()); optionParser.insert_option('b', sigc::bind<0>(sigc::ptr_fun(&rpc::call_command_set_string), "bind")); optionParser.insert_option('d', sigc::bind<0>(sigc::ptr_fun(&rpc::call_command_set_string), "directory")); @@ -303,6 +304,8 @@ main(int argc, char** argv) { // Deprecated commands. Don't use these anymore. + if (!OptionParser::has_flag('D', argc, argv)) { + rpc::parse_command_multiple (rpc::make_target(), // Deprecated in 0.7.0: @@ -347,8 +350,12 @@ main(int argc, char** argv) { "method.insert = get_memory_usage,redirect|const,pieces.memory.current\n" "method.insert = get_max_memory_usage,redirect|const,pieces.memory.max\n" "method.insert = set_max_memory_usage,redirect|const,pieces.memory.max.set\n" + + "method.insert = d.get_peer_exchange,redirect|const,d.peer_exchange\n" ); + } + if (OptionParser::has_flag('n', argc, argv)) control->core()->push_log("Ignoring ~/.rtorrent.rc."); else diff --git a/src/ui/download.cc b/src/ui/download.cc index 78f74001..9cbc6219 100644 --- a/src/ui/download.cc +++ b/src/ui/download.cc @@ -163,7 +163,7 @@ Download::create_info() { element->push_back(""); element->push_column("Chunks:", te_command("cat=$d.get_completed_chunks=,\" / \",$d.get_size_chunks=,\" * \",$d.get_chunk_size=")); element->push_column("Priority:", te_command("d.get_priority=")); - element->push_column("Peer exchange:", te_command("cat=$if=$d.get_peer_exchange=\\,enabled\\,disabled,\\ ," + element->push_column("Peer exchange:", te_command("cat=$if=$d.peer_exchange=\\,enabled\\,disabled,\\ ," "$if=$d.is_pex_active=\\,active\\,$d.is_private=\\,private\\,inactive," "\\ (,$d.get_size_pex=,/,$d.get_max_size_pex=,)"));