From 86a3f868df89f1dd1a1e810db655fe9cf37bc4dc Mon Sep 17 00:00:00 2001 From: rakshasa Date: Sat, 18 Mar 2006 00:55:50 +0000 Subject: [PATCH] * Added "send_buffer_size" and "receive_buffer_size" options that set the socket SND/RCBBUF sizes. * Added slot for connection filtering. * Added closing torrents with ^K and did some cleanup of the torrent state code. * Moved various socket setup to HandshakeManager. * Added a baseline for the uploaded amount that resets every time the torrent restarts, thereby sending only the amount uploaded since the last restart. git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@652 e378c898-3ddf-0310-93e7-cc216c733640 --- configure.ac | 4 +- src/core/download.cc | 6 +++ src/core/download.h | 3 ++ src/core/download_factory.cc | 11 ++-- src/core/download_list.cc | 95 +++++++++++++++++++++++++-------- src/core/download_list.h | 6 ++- src/core/manager.cc | 77 ++------------------------ src/core/manager.h | 6 --- src/display/window_peer_info.cc | 7 +++ src/main.cc | 6 ++- src/option_handler_rules.cc | 14 +++-- src/ui/download_list.cc | 17 ++++-- src/ui/download_list.h | 1 + 13 files changed, 134 insertions(+), 119 deletions(-) diff --git a/configure.ac b/configure.ac index 481753df..b4c5b810 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT(rtorrent, 0.4.6, jaris@ifi.uio.no) +AC_INIT(rtorrent, 0.5.0, jaris@ifi.uio.no) AM_INIT_AUTOMAKE AM_CONFIG_HEADER(config.h) @@ -24,7 +24,7 @@ TORRENT_OTFD() TORRENT_WITHOUT_VARIABLE_FDSET() -PKG_CHECK_MODULES(STUFF, sigc++-2.0 libtorrent >= 0.8.0, +PKG_CHECK_MODULES(STUFF, sigc++-2.0 libtorrent >= 0.9.0, CXXFLAGS="$CXXFLAGS $STUFF_CFLAGS $CURL_CFLAGS"; LIBS="$LIBS $STUFF_LIBS $CURL_LIBS") diff --git a/src/core/download.cc b/src/core/download.cc index 61963b20..d52c9171 100644 --- a/src/core/download.cc +++ b/src/core/download.cc @@ -106,9 +106,15 @@ Download::start() { // Update the priority to ensure it has the correct // seeding/unfinished modifiers. set_priority(priority()); + m_download.start(); } +void +Download::stop() { + m_download.stop(); +} + void Download::enable_udp_trackers(bool state) { for (int i = 0, last = m_download.size_trackers(); i < last; ++i) diff --git a/src/core/download.h b/src/core/download.h index c7187582..44cb6d09 100644 --- a/src/core/download.h +++ b/src/core/download.h @@ -56,6 +56,9 @@ public: inline bool is_done(); void start(); + void stop(); + + // Add functions like pause/etc. utils::VariableMap* variables() { return &m_variables; } std::string variable_string(const std::string& key) { return m_variables.get_string(key); } diff --git a/src/core/download_factory.cc b/src/core/download_factory.cc index 7d28cb5d..8c09525f 100644 --- a/src/core/download_factory.cc +++ b/src/core/download_factory.cc @@ -140,7 +140,7 @@ DownloadFactory::receive_success() { if (m_stream == NULL) throw torrent::client_error("DownloadFactory::receive_success() called on an object with m_stream == NULL"); - Manager::DListItr itr = m_manager->insert(m_stream, m_printLog); + DownloadList::iterator itr = m_manager->download_list().insert(m_stream, m_printLog); if (itr == m_manager->download_list().end()) { // core::Manager should already have added the error message to @@ -190,10 +190,7 @@ DownloadFactory::receive_success() { if (control->variables()->get_string("use_udp_trackers") == "no") (*itr)->enable_udp_trackers(false); - if (control->variables()->get_string("upload_total_clear") == "yes") - rtorrent.erase_key("total_uploaded"); - - else if (rtorrent.has_key("total_uploaded") && rtorrent.get_key("total_uploaded").is_value()) + if (rtorrent.has_key("total_uploaded") && rtorrent.get_key("total_uploaded").is_value()) (*itr)->get_download().up_rate()->set_total(rtorrent.get_key("total_uploaded").as_value()); if (m_session) { @@ -204,7 +201,7 @@ DownloadFactory::receive_success() { (*itr)->variables()->set("directory", rtorrent.get_key("directory")); if ((*itr)->variables()->get_string("state") == "started") - m_manager->start(*itr, m_printLog); + m_manager->download_list().resume(*itr); } else { (*itr)->variables()->set("directory", m_variables.get("directory")); @@ -213,7 +210,7 @@ DownloadFactory::receive_success() { (*itr)->variables()->set("tied_to_file", m_uri); if (m_start) - m_manager->start(*itr, m_printLog); + m_manager->download_list().start(*itr); m_manager->download_store().save(*itr); } diff --git a/src/core/download_list.cc b/src/core/download_list.cc index f61161d4..7ca44a0d 100644 --- a/src/core/download_list.cc +++ b/src/core/download_list.cc @@ -38,10 +38,14 @@ #include #include +#include #include #include "rak/functional.h" +#include "globals.h" +#include "manager.h" + #include "download.h" #include "download_list.h" @@ -58,19 +62,33 @@ struct download_list_call { }; DownloadList::iterator -DownloadList::insert(std::istream* str) { - torrent::Download d = torrent::download_add(str); +DownloadList::insert(std::istream* str, bool printLog) { + try { - iterator itr = Base::insert(end(), new Download(d)); - (*itr)->get_download().signal_download_done(sigc::bind(sigc::mem_fun(*this, &DownloadList::finished), *itr)); + torrent::Download d = torrent::download_add(str); - std::for_each(m_slotMapInsert.begin(), m_slotMapInsert.end(), download_list_call(*itr)); + iterator itr = Base::insert(end(), new Download(d)); - return itr; + (*itr)->get_download().signal_download_done(sigc::bind(sigc::mem_fun(*this, &DownloadList::finished), *itr)); + std::for_each(m_slotMapInsert.begin(), m_slotMapInsert.end(), download_list_call(*itr)); + + return itr; + + } catch (torrent::local_error& e) { + if (printLog) + control->core()->push_log(e.what()); + + return end(); + } } DownloadList::iterator DownloadList::erase(iterator itr) { + // Make safe to erase active downloads. + + if ((*itr)->get_download().is_active()) + throw std::logic_error("DownloadList::erase(...) called on an active download."); + std::for_each(m_slotMapErase.begin(), m_slotMapErase.end(), download_list_call(*itr)); torrent::download_remove((*itr)->get_download()); @@ -81,37 +99,72 @@ DownloadList::erase(iterator itr) { void DownloadList::open(Download* d) { - if (d->get_download().is_open()) - return; + try { - std::for_each(m_slotMapOpen.begin(), m_slotMapOpen.end(), download_list_call(d)); + if (!d->get_download().is_open()) + std::for_each(m_slotMapOpen.begin(), m_slotMapOpen.end(), download_list_call(d)); + + } catch (torrent::local_error& e) { + control->core()->push_log(e.what()); + } } void DownloadList::close(Download* d) { - if (!d->get_download().is_open()) - return; + try { - stop(d); - std::for_each(m_slotMapClose.begin(), m_slotMapClose.end(), download_list_call(d)); + if (d->get_download().is_active()) + std::for_each(m_slotMapStop.begin(), m_slotMapStop.end(), download_list_call(d)); + + if (d->get_download().is_open()) + std::for_each(m_slotMapClose.begin(), m_slotMapClose.end(), download_list_call(d)); + + } catch (torrent::local_error& e) { + control->core()->push_log(e.what()); + } } void DownloadList::start(Download* d) { - if (d->get_download().is_active() || - !d->get_download().is_hash_checked()) - return; + d->variables()->set("state", "started"); - open(d); - std::for_each(m_slotMapStart.begin(), m_slotMapStart.end(), download_list_call(d)); + resume(d); } void DownloadList::stop(Download* d) { - if (!d->get_download().is_active()) - return; + d->variables()->set("state", "stopped"); - std::for_each(m_slotMapStop.begin(), m_slotMapStop.end(), download_list_call(d)); + pause(d); +} + +void +DownloadList::resume(Download* d) { + try { + if (!d->get_download().is_open()) + std::for_each(m_slotMapOpen.begin(), m_slotMapOpen.end(), download_list_call(d)); + + if (d->get_download().is_hash_checked()) + std::for_each(m_slotMapStart.begin(), m_slotMapStart.end(), download_list_call(d)); + else + // TODO: This can cause infinit looping? + control->core()->hash_queue().insert(d, sigc::bind(sigc::mem_fun(*this, &DownloadList::resume), d)); + + } catch (torrent::local_error& e) { + control->core()->push_log(e.what()); + } +} + +void +DownloadList::pause(Download* d) { + try { + + if (d->get_download().is_active()) + std::for_each(m_slotMapStop.begin(), m_slotMapStop.end(), download_list_call(d)); + + } catch (torrent::local_error& e) { + control->core()->push_log(e.what()); + } } void diff --git a/src/core/download_list.h b/src/core/download_list.h index 431a0460..6059757a 100644 --- a/src/core/download_list.h +++ b/src/core/download_list.h @@ -73,7 +73,7 @@ public: ~DownloadList() { clear(); } - iterator insert(std::istream* str); + iterator insert(std::istream* str, bool printLog); iterator erase(iterator itr); void open(Download* d); @@ -82,6 +82,10 @@ public: void start(Download* d); void stop(Download* d); + // These do not change the rtorrent:state. + void resume(Download* d); + void pause(Download* d); + SlotMap& slot_map_insert() { return m_slotMapInsert; } SlotMap& slot_map_erase() { return m_slotMapErase; } SlotMap& slot_map_open() { return m_slotMapOpen; } diff --git a/src/core/manager.cc b/src/core/manager.cc index c8a57a10..b9082808 100644 --- a/src/core/manager.cc +++ b/src/core/manager.cc @@ -130,7 +130,7 @@ Manager::initialize_second() { m_downloadList.slot_map_start()["1_download_start"] = sigc::mem_fun(&Download::start); - m_downloadList.slot_map_stop()["1_download_stop"] = sigc::mem_fun(&Download::call); + m_downloadList.slot_map_stop()["1_download_stop"] = sigc::mem_fun(&Download::stop); m_downloadList.slot_map_stop()["2_hash_resume_save"] = sigc::mem_fun(&Download::call); m_downloadList.slot_map_stop()["3_store_save"] = sigc::mem_fun(m_downloadStore, &DownloadStore::save); @@ -152,75 +152,9 @@ Manager::cleanup() { void Manager::shutdown(bool force) { if (!force) - std::for_each(m_downloadList.begin(), m_downloadList.end(), - std::bind1st(std::mem_fun(&DownloadList::stop), &m_downloadList)); + std::for_each(m_downloadList.begin(), m_downloadList.end(), std::bind1st(std::mem_fun(&DownloadList::pause), &m_downloadList)); else - std::for_each(m_downloadList.begin(), m_downloadList.end(), - std::bind1st(std::mem_fun(&DownloadList::close), &m_downloadList)); -} - -Manager::DListItr -Manager::insert(std::istream* s, bool printLog) { - try { - return m_downloadList.insert(s); - - } catch (torrent::local_error& e) { - if (printLog) { - m_logImportant.push_front(e.what()); - m_logComplete.push_front(e.what()); - } - - return m_downloadList.end(); - } -} - -Manager::DListItr -Manager::erase(DListItr itr) { - if ((*itr)->get_download().is_active()) - throw std::logic_error("core::Manager::erase(...) called on an active download"); - -// if (!(*itr)->get_download().is_open()) -// throw std::logic_error("core::Manager::erase(...) called on an closed download"); - - return m_downloadList.erase(itr); -} - -void -Manager::start(Download* d, bool printLog) { - try { - d->variables()->set("state", "started"); - - if (d->get_download().is_active()) - return; - - if (!d->get_download().is_open()) - m_downloadList.open(d); - - if (d->get_download().is_hash_checked()) - m_downloadList.start(d); - else - // This can cause infinit loops? - m_hashQueue.insert(d, sigc::bind(sigc::mem_fun(m_downloadList, &DownloadList::start), d)); - - } catch (torrent::local_error& e) { - if (printLog) { - m_logImportant.push_front(e.what()); - m_logComplete.push_front(e.what()); - } - } -} - -void -Manager::stop(Download* d) { - try { - d->variables()->set("state", "stopped"); - - m_downloadList.stop(d); - - } catch (torrent::local_error& e) { - m_logImportant.push_front(e.what()); - m_logComplete.push_front(e.what()); - } + std::for_each(m_downloadList.begin(), m_downloadList.end(), std::bind1st(std::mem_fun(&DownloadList::close), &m_downloadList)); } void @@ -231,7 +165,7 @@ Manager::check_hash(Download* d) { prepare_hash_check(d); if (restart) - m_hashQueue.insert(d, sigc::bind(sigc::mem_fun(m_downloadList, &DownloadList::start), d)); + m_hashQueue.insert(d, sigc::bind(sigc::mem_fun(m_downloadList, &DownloadList::resume), d)); else m_hashQueue.insert(d, sigc::slot0()); @@ -350,8 +284,7 @@ Manager::receive_http_failed(std::string msg) { void Manager::receive_download_done_hash_checked(Download* d) { - if (!d->get_download().is_active()) - m_downloadList.start(d); + m_downloadList.resume(d); if (control->variables()->get_string("session_on_completion") == "yes") m_downloadStore.save(d); diff --git a/src/core/manager.h b/src/core/manager.h index 0ed8c329..35be6945 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -83,12 +83,6 @@ public: void shutdown(bool force); - DListItr insert(std::istream* s, bool printLog = true); - DListItr erase(DListItr itr); - - void start(Download* d, bool printLog = true); - void stop(Download* d); - void check_hash(Download* d); void push_log(const std::string& msg) { m_logImportant.push_front(msg); m_logComplete.push_front(msg); } diff --git a/src/display/window_peer_info.cc b/src/display/window_peer_info.cc index 3f45fa4d..edfb15dd 100644 --- a/src/display/window_peer_info.cc +++ b/src/display/window_peer_info.cc @@ -40,6 +40,7 @@ #include #include #include +#include #include "core/download.h" @@ -94,6 +95,12 @@ WindowPeerInfo::redraw() { y++; + // Temporary. +// m_canvas->print(0, y++, "SndBuf: %u", torrent::connection_manager()->send_buffer_size()); +// m_canvas->print(0, y++, "RcvBuf: %u", torrent::connection_manager()->receive_buffer_size()); + +// y++; + if (*m_focus == m_list->end()) { m_canvas->print(0, y++, "No peer in focus"); diff --git a/src/main.cc b/src/main.cc index 5d77e2c2..fac2bb1f 100644 --- a/src/main.cc +++ b/src/main.cc @@ -148,8 +148,6 @@ main(int argc, char** argv) { srandom(cachedTime.usec()); srand48(cachedTime.usec()); - initialize_option_handler(control); - SignalHandler::set_ignore(SIGPIPE); SignalHandler::set_handler(SIGINT, sigc::mem_fun(control, &Control::receive_normal_shutdown)); SignalHandler::set_handler(SIGTERM, sigc::mem_fun(control, &Control::receive_quick_shutdown)); @@ -160,6 +158,10 @@ main(int argc, char** argv) { control->core()->initialize_first(); + // Initialize option handlers after libtorrent to ensure + // torrent::ConnectionManager* is valid etc. + initialize_option_handler(control); + // Move env and go through "try_import". if (!control->variables()->process_file("~/.rtorrent.rc")) control->core()->get_log_important().push_front("Could not load \"~/.rtorrent.rc\"."); diff --git a/src/option_handler_rules.cc b/src/option_handler_rules.cc index 0c61d49d..fa900825 100644 --- a/src/option_handler_rules.cc +++ b/src/option_handler_rules.cc @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -119,7 +120,7 @@ apply_stop_untied(Control* m, __UNUSED const std::string& arg) { if (!fs.update(rak::path_expand((*itr)->variable_string("tied_to_file")))) { (*itr)->variables()->set("tied_to_file", std::string()); - m->core()->stop(*itr); + m->core()->download_list().stop(*itr); } ++itr; @@ -138,8 +139,8 @@ apply_remove_untied(Control* m, __UNUSED const std::string& arg) { if (!fs.update(rak::path_expand((*itr)->variable_string("tied_to_file")))) { (*itr)->variables()->set("tied_to_file", std::string()); - m->core()->stop(*itr); - itr = m->core()->erase(itr); + m->core()->download_list().stop(*itr); + itr = m->core()->download_list().erase(itr); } else { ++itr; @@ -180,7 +181,6 @@ initialize_option_handler(Control* c) { variables->insert("download_rate", new utils::VariableSlotValue(NULL, rak::mem_fn(control->ui(), &ui::Root::set_down_throttle), "%i")); variables->insert("upload_rate", new utils::VariableSlotValue(NULL, rak::mem_fn(control->ui(), &ui::Root::set_up_throttle), "%i")); - variables->insert("upload_total_clear", new utils::VariableAny("no")); variables->insert("hash_max_tries", new utils::VariableSlotValue(NULL, rak::ptr_fn(&torrent::set_hash_max_tries), "%i")); variables->insert("max_open_files", new utils::VariableSlotValue(NULL, rak::ptr_fn(&torrent::set_max_open_files), "%i")); @@ -193,6 +193,12 @@ initialize_option_handler(Control* c) { variables->insert("schedule", new utils::VariableSlotString<>(NULL, rak::mem_fn(c->command_scheduler(), &CommandScheduler::parse))); variables->insert("schedule_remove", new utils::VariableSlotString<>(NULL, rak::mem_fn(c->command_scheduler(), &CommandScheduler::erase))); + variables->insert("send_buffer_size", new utils::VariableSlotValue(NULL, rak::mem_fn(torrent::connection_manager(), + &torrent::ConnectionManager::set_send_buffer_size), "%u")); + + variables->insert("receive_buffer_size", new utils::VariableSlotValue(NULL, rak::mem_fn(torrent::connection_manager(), + &torrent::ConnectionManager::set_receive_buffer_size), "%u")); + // Old. variables->insert("port_range", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_port_range, c))); diff --git a/src/ui/download_list.cc b/src/ui/download_list.cc index 7f5ed04f..fb2426a5 100644 --- a/src/ui/download_list.cc +++ b/src/ui/download_list.cc @@ -192,7 +192,7 @@ DownloadList::receive_start_download() { if (m_downloadList.get_focus() == m_downloadList.end()) return; - m_control->core()->start(*m_downloadList.get_focus()); + m_control->core()->download_list().start(*m_downloadList.get_focus()); } void @@ -201,9 +201,17 @@ DownloadList::receive_stop_download() { return; if ((*m_downloadList.get_focus())->get_download().is_active()) - m_control->core()->stop(*m_downloadList.get_focus()); + m_control->core()->download_list().stop(*m_downloadList.get_focus()); else - m_downloadList.set_focus(m_control->core()->erase(m_downloadList.get_focus())); + m_downloadList.set_focus(m_control->core()->download_list().erase(m_downloadList.get_focus())); +} + +void +DownloadList::receive_close_download() { + if (m_downloadList.get_focus() == m_downloadList.end()) + return; + + m_control->core()->download_list().close(*m_downloadList.get_focus()); } void @@ -308,7 +316,7 @@ DownloadList::receive_exit_input(Input type) { throw torrent::input_error("No download in focus to change root directory."); (*m_downloadList.get_focus())->variables()->set("directory", rak::trim(m_windowTextInput->get_input()->str())); - m_control->core()->push_log("New root dir \"" + (*m_downloadList.get_focus())->variables()->get_string("directory") + "\""); + m_control->core()->push_log("New root dir \"" + (*m_downloadList.get_focus())->variables()->get_string("directory") + "\" for torrent."); break; case INPUT_COMMAND: @@ -366,6 +374,7 @@ void DownloadList::setup_keys() { (*m_bindings)['\x13'] = sigc::mem_fun(*this, &DownloadList::receive_start_download); (*m_bindings)['\x04'] = sigc::mem_fun(*this, &DownloadList::receive_stop_download); + (*m_bindings)['\x0B'] = sigc::mem_fun(*this, &DownloadList::receive_close_download); (*m_bindings)['\x12'] = sigc::mem_fun(*this, &DownloadList::receive_check_hash); (*m_bindings)['+'] = sigc::mem_fun(*this, &DownloadList::receive_next_priority); (*m_bindings)['-'] = sigc::mem_fun(*this, &DownloadList::receive_prev_priority); diff --git a/src/ui/download_list.h b/src/ui/download_list.h index 7c4d3707..56cb5a97 100644 --- a/src/ui/download_list.h +++ b/src/ui/download_list.h @@ -119,6 +119,7 @@ private: void receive_start_download(); void receive_stop_download(); + void receive_close_download(); void receive_view_download(); void receive_exit_download();