diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index 0806b8c5..103ab677 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -11,6 +11,12 @@ jobs: - name: Update Packages run: | sudo apt-get update + - name: Install Dependencies + run: | + sudo apt-get install -y \ + bear \ + clang-tidy \ + libcurl4-openssl-dev - name: Fetch libtorrent run: | git clone https://github.com/rakshasa/libtorrent @@ -35,9 +41,6 @@ jobs: run: | git remote add upstream "https://github.com/${{ github.event.pull_request.base.repo.full_name }}" git fetch --no-tags --no-recurse-submodules upstream "${{ github.event.pull_request.base.ref }}" - - name: Install Dependencies - run: | - sudo apt-get install -y bear clang-tidy libcurl4-openssl-dev - name: Configure Project run: | libtoolize diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index eb46af68..293784a4 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -11,6 +11,11 @@ jobs: - name: Update Packages run: | sudo apt-get update + - name: Install Dependencies + run: | + sudo apt-get install -y \ + libcppunit-dev \ + libcurl4-openssl-dev - name: Fetch libtorrent run: | git clone https://github.com/rakshasa/libtorrent @@ -35,11 +40,6 @@ jobs: run: | git remote add upstream "https://github.com/${{ github.event.pull_request.base.repo.full_name }}" git fetch --no-tags --no-recurse-submodules upstream "${{ github.event.pull_request.base.ref }}" - - name: Install Dependencies - run: | - sudo apt-get install -y \ - libcppunit-dev \ - libcurl4-openssl-dev - name: Configure Project run: | libtoolize @@ -53,4 +53,12 @@ jobs: make - name: Run Unit Tests run: | + ls /usr/local/lib/ + export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib" make check + - name: Archive test/test-suite.log + if: success() || failure() + uses: actions/upload-artifact@v4 + with: + name: test-suite.log + path: test/test-suite.log diff --git a/configure.ac b/configure.ac index f719141f..a204852a 100644 --- a/configure.ac +++ b/configure.ac @@ -52,7 +52,6 @@ if test "x$ax_cv_ncursesw" != xyes && test "x$ax_cv_ncurses" != xyes; then AC_MSG_ERROR([requires either NcursesW or Ncurses library]) fi -PKG_CHECK_MODULES([LIBCURL], [libcurl],, [LIBCURL_CHECK_CONFIG]) PKG_CHECK_MODULES([CPPUNIT], [cppunit],, [no_cppunit="yes"]) PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.15.4]) @@ -74,9 +73,9 @@ AC_CHECK_FUNCS(posix_memalign) dnl Only update global build variables immediately before generating the output, dnl to avoid affecting the global build environment for other autoconf checks. -LIBS="$PTHREAD_LIBS $CURSES_LIB $CURSES_LIBS $LIBCURL $LIBCURL_LIBS $DEPENDENCIES_LIBS $LIBS" -CFLAGS="$CFLAGS $PTHREAD_CFLAGS $LIBCURL_CPPFLAGS $LIBCURL_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS" -CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS $LIBCURL_CPPFLAGS $LIBCURL_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS" +LIBS="$PTHREAD_LIBS $CURSES_LIB $CURSES_LIBS $DEPENDENCIES_LIBS $LIBS" +CFLAGS="$CFLAGS $PTHREAD_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS" +CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS $DEPENDENCIES_CFLAGS $CURSES_CFLAGS" TORRENT_CHECK_CACHELINE() TORRENT_CHECK_POPCOUNT() diff --git a/src/Makefile.am b/src/Makefile.am index 4b6f2666..9dee76b5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,12 +5,6 @@ rtorrent_LDADD = libsub_root.a @PTHREAD_LIBS@ rtorrent_SOURCES = main.cc libsub_root_a_SOURCES = \ - core/curl_get.cc \ - core/curl_get.h \ - core/curl_socket.cc \ - core/curl_socket.h \ - core/curl_stack.cc \ - core/curl_stack.h \ core/dht_manager.cc \ core/dht_manager.h \ core/download.cc \ diff --git a/src/command_network.cc b/src/command_network.cc index 45a94ba5..0127fca9 100644 --- a/src/command_network.cc +++ b/src/command_network.cc @@ -5,16 +5,16 @@ #include #include #include -#include -#include #include #include +#include #include #include +#include +#include #include #include -#include "core/curl_stack.h" #include "core/download.h" #include "core/manager.h" #include "rpc/scgi.h" @@ -189,9 +189,9 @@ apply_xmlrpc_dialect(const std::string& arg) { void initialize_command_network() { - torrent::ConnectionManager* cm = torrent::connection_manager(); - torrent::FileManager* fileManager = torrent::file_manager(); - core::CurlStack* httpStack = control->core()->http_stack(); + auto cm = torrent::connection_manager(); + auto fileManager = torrent::file_manager(); + auto http_stack = torrent::net_thread::http_stack(); CMD2_ANY_STRING ("encoding.add", std::bind(&apply_encoding_list, std::placeholders::_2)); @@ -215,21 +215,21 @@ initialize_command_network() { CMD2_VAR_STRING ("protocol.choke_heuristics.down.leech", "download_leech"); CMD2_VAR_STRING ("protocol.choke_heuristics.down.seed", "download_leech"); - CMD2_ANY ("network.http.cacert", std::bind(&core::CurlStack::http_cacert, httpStack)); - CMD2_ANY_STRING_V("network.http.cacert.set", std::bind(&core::CurlStack::set_http_cacert, httpStack, std::placeholders::_2)); - CMD2_ANY ("network.http.capath", std::bind(&core::CurlStack::http_capath, httpStack)); - CMD2_ANY_STRING_V("network.http.capath.set", std::bind(&core::CurlStack::set_http_capath, httpStack, std::placeholders::_2)); - CMD2_ANY ("network.http.dns_cache_timeout", std::bind(&core::CurlStack::dns_timeout, httpStack)); - CMD2_ANY_VALUE_V ("network.http.dns_cache_timeout.set", std::bind(&core::CurlStack::set_dns_timeout, httpStack, std::placeholders::_2)); - CMD2_ANY ("network.http.current_open", std::bind(&core::CurlStack::active, httpStack)); - CMD2_ANY ("network.http.max_open", std::bind(&core::CurlStack::max_active, httpStack)); - CMD2_ANY_VALUE_V ("network.http.max_open.set", std::bind(&core::CurlStack::set_max_active, httpStack, std::placeholders::_2)); - CMD2_ANY ("network.http.proxy_address", std::bind(&core::CurlStack::http_proxy, httpStack)); - CMD2_ANY_STRING_V("network.http.proxy_address.set", std::bind(&core::CurlStack::set_http_proxy, httpStack, std::placeholders::_2)); - CMD2_ANY ("network.http.ssl_verify_host", std::bind(&core::CurlStack::ssl_verify_host, httpStack)); - CMD2_ANY_VALUE_V ("network.http.ssl_verify_host.set", std::bind(&core::CurlStack::set_ssl_verify_host, httpStack, std::placeholders::_2)); - CMD2_ANY ("network.http.ssl_verify_peer", std::bind(&core::CurlStack::ssl_verify_peer, httpStack)); - CMD2_ANY_VALUE_V ("network.http.ssl_verify_peer.set", std::bind(&core::CurlStack::set_ssl_verify_peer, httpStack, std::placeholders::_2)); + CMD2_ANY ("network.http.cacert", [http_stack](auto, auto) { return http_stack->http_cacert(); }); + CMD2_ANY_STRING_V("network.http.cacert.set", [http_stack](auto, auto& str) { return http_stack->set_http_cacert(str); }); + CMD2_ANY ("network.http.capath", [http_stack](auto, auto) { return http_stack->http_capath(); }); + CMD2_ANY_STRING_V("network.http.capath.set", [http_stack](auto, auto& str) { return http_stack->set_http_capath(str); }); + CMD2_ANY ("network.http.dns_cache_timeout", [http_stack](auto, auto) { return http_stack->dns_timeout(); }); + CMD2_ANY_VALUE_V ("network.http.dns_cache_timeout.set", [http_stack](auto, auto& value) { return http_stack->set_dns_timeout(value); }); + CMD2_ANY ("network.http.current_open", [http_stack](auto, auto) { return http_stack->active(); }); + CMD2_ANY ("network.http.max_open", [http_stack](auto, auto) { return http_stack->max_active(); }); + CMD2_ANY_VALUE_V ("network.http.max_open.set", [http_stack](auto, auto& value) { return http_stack->set_max_active(value); }); + CMD2_ANY ("network.http.proxy_address", [http_stack](auto, auto) { return http_stack->http_proxy(); }); + CMD2_ANY_STRING_V("network.http.proxy_address.set", [http_stack](auto, auto& str) { return http_stack->set_http_proxy(str); }); + CMD2_ANY ("network.http.ssl_verify_host", [http_stack](auto, auto) { return http_stack->ssl_verify_host(); }); + CMD2_ANY_VALUE_V ("network.http.ssl_verify_host.set", [http_stack](auto, auto& value) { return http_stack->set_ssl_verify_host(value); }); + CMD2_ANY ("network.http.ssl_verify_peer", [http_stack](auto, auto) { return http_stack->ssl_verify_peer(); }); + CMD2_ANY_VALUE_V ("network.http.ssl_verify_peer.set", [http_stack](auto, auto& value) { return http_stack->set_ssl_verify_peer(value); }); CMD2_ANY ("network.send_buffer.size", std::bind(&torrent::ConnectionManager::send_buffer_size, cm)); CMD2_ANY_VALUE_V ("network.send_buffer.size.set", std::bind(&torrent::ConnectionManager::set_send_buffer_size, cm, std::placeholders::_2)); diff --git a/src/control.cc b/src/control.cc index 2d39c08d..9007f5e4 100644 --- a/src/control.cc +++ b/src/control.cc @@ -1,11 +1,13 @@ #include "config.h" +#include "control.h" + #include #include #include +#include #include -#include "core/curl_stack.h" #include "core/dht_manager.h" #include "core/download_store.h" #include "core/http_queue.h" @@ -26,10 +28,8 @@ #include "rpc/object_storage.h" #include "ui/root.h" -#include "control.h" - -Control::Control() : - m_ui(new ui::Root()), +Control::Control() + : m_ui(new ui::Root()), m_display(new display::Manager()), m_input(new input::Manager()), m_inputStdin(new input::InputEvent(STDIN_FILENO)), @@ -38,11 +38,11 @@ Control::Control() : m_lua_engine(new rpc::LuaEngine()), m_directory_events(new torrent::directory_events()) { - m_core = new core::Manager(); - m_viewManager = new core::ViewManager(); - m_dhtManager = new core::DhtManager(); + m_core = std::make_unique(); + m_viewManager = std::make_unique(); + m_dhtManager = std::make_unique(); - m_inputStdin->slot_pressed(std::bind(&input::Manager::pressed, m_input, std::placeholders::_1)); + m_inputStdin->slot_pressed(std::bind(&input::Manager::pressed, m_input.get(), std::placeholders::_1)); m_task_shutdown.slot() = std::bind(&Control::handle_shutdown, this); @@ -50,20 +50,10 @@ Control::Control() : } Control::~Control() { - delete m_inputStdin; - delete m_input; + m_viewManager.reset(); - delete m_viewManager; - - delete m_ui; - delete m_display; - delete m_core; - delete m_dhtManager; - - delete m_directory_events; - delete m_commandScheduler; - delete m_objectStorage; - delete m_lua_engine; + m_ui.reset(); + m_display.reset(); } void @@ -73,9 +63,8 @@ Control::initialize() { display::Window::slot_unschedule([this](display::Window* w) { m_display->unschedule(w); }); display::Window::slot_adjust([this]() { m_display->adjust_layout(); }); - m_core->http_stack()->set_user_agent(USER_AGENT); + torrent::net_thread::http_stack()->set_user_agent(USER_AGENT); - m_core->initialize_second(); m_core->listen_open(); m_core->download_store()->enable(rpc::call_command_value("session.use_lock")); @@ -122,7 +111,10 @@ Control::is_shutdown_completed() { // Tracker requests can be disowned, so wait for these to // finish. The edge case of torrent http downloads may delay // shutdown. - if (!core()->http_stack()->empty() || !core()->http_queue()->empty()) + + // TODO: We keep http requests in the queue for a while after, so improve this check to ignore + // those. + if (torrent::net_thread::http_stack()->active() != 0 || !core()->http_queue()->empty()) return false; return torrent::is_inactive(); diff --git a/src/control.h b/src/control.h index ee56307c..8478122f 100644 --- a/src/control.h +++ b/src/control.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -55,20 +56,20 @@ public: void receive_normal_shutdown() { m_shutdownReceived = true; } void receive_quick_shutdown() { m_shutdownReceived = true; m_shutdownQuick = true; } - core::Manager* core() { return m_core; } - core::ViewManager* view_manager() { return m_viewManager; } - core::DhtManager* dht_manager() { return m_dhtManager; } + core::Manager* core() { return m_core.get(); } + core::ViewManager* view_manager() { return m_viewManager.get(); } + core::DhtManager* dht_manager() { return m_dhtManager.get(); } - ui::Root* ui() { return m_ui; } - display::Manager* display() { return m_display; } - input::Manager* input() { return m_input; } - input::InputEvent* input_stdin() { return m_inputStdin; } + ui::Root* ui() { return m_ui.get(); } + display::Manager* display() { return m_display.get(); } + input::Manager* input() { return m_input.get(); } + input::InputEvent* input_stdin() { return m_inputStdin.get(); } - rpc::CommandScheduler* command_scheduler() { return m_commandScheduler; } - rpc::object_storage* object_storage() { return m_objectStorage; } - rpc::LuaEngine* lua_engine() { return m_lua_engine; } + rpc::CommandScheduler* command_scheduler() { return m_commandScheduler.get(); } + rpc::object_storage* object_storage() { return m_objectStorage.get(); } + rpc::LuaEngine* lua_engine() { return m_lua_engine.get(); } - torrent::directory_events* directory_events() { return m_directory_events; } + torrent::directory_events* directory_events() { return m_directory_events.get(); } uint64_t tick() const { return m_tick; } void inc_tick() { m_tick++; } @@ -80,19 +81,19 @@ private: Control(const Control&); void operator = (const Control&); - core::Manager* m_core; - core::ViewManager* m_viewManager; - core::DhtManager* m_dhtManager; + std::unique_ptr m_core; + std::unique_ptr m_viewManager; + std::unique_ptr m_dhtManager; - ui::Root* m_ui; - display::Manager* m_display; - input::Manager* m_input; - input::InputEvent* m_inputStdin; + std::unique_ptr m_ui; + std::unique_ptr m_display; + std::unique_ptr m_input; + std::unique_ptr m_inputStdin; - rpc::CommandScheduler* m_commandScheduler; - rpc::object_storage* m_objectStorage; - rpc::LuaEngine* m_lua_engine; - torrent::directory_events* m_directory_events; + std::unique_ptr m_commandScheduler; + std::unique_ptr m_objectStorage; + std::unique_ptr m_lua_engine; + std::unique_ptr m_directory_events; uint64_t m_tick{}; diff --git a/src/core/curl_get.cc b/src/core/curl_get.cc deleted file mode 100644 index 3fd72c88..00000000 --- a/src/core/curl_get.cc +++ /dev/null @@ -1,122 +0,0 @@ -#include "config.h" - -#include "core/curl_get.h" - -#include -#include -#include -#include - -#include "globals.h" -#include "core/curl_stack.h" - -namespace core { - -size_t -curl_get_receive_write(void* data, size_t size, size_t nmemb, void* handle) { - if (!((CurlGet*)handle)->stream()->write((const char*)data, size * nmemb).fail()) - return size * nmemb; - else - return 0; -} - -CurlGet::CurlGet(CurlStack* s) : - m_stack(s) { - - m_task_timeout.slot() = [this]() { receive_timeout(); }; -} - -CurlGet::~CurlGet() { - close(); -} - -void -CurlGet::start() { - if (is_busy()) - throw torrent::internal_error("Tried to call CurlGet::start on a busy object."); - - if (m_stream == NULL) - throw torrent::internal_error("Tried to call CurlGet::start without a valid output stream."); - - if (!m_stack->is_running()) - return; - - m_handle = curl_easy_init(); - - if (m_handle == NULL) - throw torrent::internal_error("Call to curl_easy_init() failed."); - - curl_easy_setopt(m_handle, CURLOPT_URL, m_url.c_str()); - curl_easy_setopt(m_handle, CURLOPT_WRITEFUNCTION, &curl_get_receive_write); - curl_easy_setopt(m_handle, CURLOPT_WRITEDATA, this); - - if (m_timeout != 0) { - curl_easy_setopt(m_handle, CURLOPT_CONNECTTIMEOUT, (long)60); - curl_easy_setopt(m_handle, CURLOPT_TIMEOUT, (long)m_timeout); - - // Normally libcurl should handle the timeout. But sometimes that doesn't - // work right so we do a fallback timeout that just aborts the transfer. - torrent::this_thread::scheduler()->update_wait_for_ceil_seconds(&m_task_timeout, 5s + 1s*m_timeout); - } - - curl_easy_setopt(m_handle, CURLOPT_FORBID_REUSE, (long)1); - curl_easy_setopt(m_handle, CURLOPT_NOSIGNAL, (long)1); - curl_easy_setopt(m_handle, CURLOPT_FOLLOWLOCATION, (long)1); - curl_easy_setopt(m_handle, CURLOPT_MAXREDIRS, (long)5); - - curl_easy_setopt(m_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER); - - curl_easy_setopt(m_handle, CURLOPT_ENCODING, ""); - - m_ipv6 = false; - - m_stack->add_get(this); -} - -void -CurlGet::close() { - torrent::this_thread::scheduler()->erase(&m_task_timeout); - - if (!is_busy()) - return; - - m_stack->remove_get(this); - - curl_easy_cleanup(m_handle); - - m_handle = NULL; -} - -void -CurlGet::retry_ipv6() { - CURL* nhandle = curl_easy_duphandle(m_handle); - - curl_easy_setopt(nhandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); - curl_easy_cleanup(m_handle); - - m_handle = nhandle; - m_ipv6 = true; -} - -void -CurlGet::receive_timeout() { - return m_stack->transfer_done(m_handle, "Timed out"); -} - -curl_off_t -CurlGet::size_done() { - curl_off_t d = 0; - curl_easy_getinfo(m_handle, CURLINFO_SIZE_DOWNLOAD_T, &d); - - return d; -} - -curl_off_t -CurlGet::size_total() { - curl_off_t d = 0; - curl_easy_getinfo(m_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &d); - - return d; -} - -} diff --git a/src/core/curl_get.h b/src/core/curl_get.h deleted file mode 100644 index 51b6a6e9..00000000 --- a/src/core/curl_get.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef RTORRENT_CORE_CURL_GET_H -#define RTORRENT_CORE_CURL_GET_H - -#include -#include -#include -#include -#include - -namespace core { - -class CurlStack; - -class CurlGet : public torrent::Http { -public: - CurlGet(CurlStack* s); - virtual ~CurlGet(); - - void start(); - void close(); - - bool is_using_ipv6() { return m_ipv6; } - void retry_ipv6(); - - bool is_busy() const { return m_handle; } - bool is_active() const { return m_active; } - - void set_active(bool a) { m_active = a; } - - curl_off_t size_done(); - curl_off_t size_total(); - - CURL* handle() { return m_handle; } - -private: - friend class CurlStack; - - CurlGet(const CurlGet&) = delete; - void operator = (const CurlGet&) = delete; - - void receive_timeout(); - - bool m_active{}; - bool m_ipv6; - - torrent::utils::SchedulerEntry m_task_timeout; - - CURL* m_handle{}; - CurlStack* m_stack; -}; - -} - -#endif diff --git a/src/core/curl_socket.cc b/src/core/curl_socket.cc deleted file mode 100644 index b72e3e57..00000000 --- a/src/core/curl_socket.cc +++ /dev/null @@ -1,99 +0,0 @@ -#include "config.h" - -#include "curl_socket.h" - -#include -#include -#include -#include -#include - -#include "control.h" -#include "core/curl_stack.h" - -namespace core { - -int -CurlSocket::receive_socket([[maybe_unused]] void* easy_handle, curl_socket_t fd, int what, void* userp, void* socketp) { - CurlStack* stack = (CurlStack*)userp; - CurlSocket* socket = (CurlSocket*)socketp; - - if (!stack->is_running()) - return 0; - - if (what == CURL_POLL_REMOVE) { - // We also probably need the special code here as we're not - // guaranteed that the fd will be closed, afaik. - if (socket != NULL) - socket->close(); - - // TODO: Consider the possibility that we'll need to set the - // fd-associated pointer curl holds to NULL. - - delete socket; - return 0; - } - - if (socket == NULL) { - socket = stack->new_socket(fd); - torrent::this_thread::poll()->open(socket); - - // No interface for libcurl to signal when it's interested in error events. - // Assume that hence it must always be interested in them. - torrent::this_thread::poll()->insert_error(socket); - } - - if (what == CURL_POLL_NONE || what == CURL_POLL_OUT) - torrent::this_thread::poll()->remove_read(socket); - else - torrent::this_thread::poll()->insert_read(socket); - - if (what == CURL_POLL_NONE || what == CURL_POLL_IN) - torrent::this_thread::poll()->remove_write(socket); - else - torrent::this_thread::poll()->insert_write(socket); - - return 0; -} - -CurlSocket::~CurlSocket() { - assert(m_fileDesc == -1 && "CurlSocket::~CurlSocket() m_fileDesc != -1."); -} - -void -CurlSocket::close() { - if (m_fileDesc == -1) - throw torrent::internal_error("CurlSocket::close() m_fileDesc == -1."); - - torrent::this_thread::poll()->closed(this); - m_fileDesc = -1; -} - -void -CurlSocket::event_read() { -#if (LIBCURL_VERSION_NUM >= 0x071003) - return m_stack->receive_action(this, CURL_CSELECT_IN); -#else - return m_stack->receive_action(this, 0); -#endif -} - -void -CurlSocket::event_write() { -#if (LIBCURL_VERSION_NUM >= 0x071003) - return m_stack->receive_action(this, CURL_CSELECT_OUT); -#else - return m_stack->receive_action(this, 0); -#endif -} - -void -CurlSocket::event_error() { -#if (LIBCURL_VERSION_NUM >= 0x071003) - return m_stack->receive_action(this, CURL_CSELECT_ERR); -#else - return m_stack->receive_action(this, 0); -#endif -} - -} diff --git a/src/core/curl_socket.h b/src/core/curl_socket.h deleted file mode 100644 index 20999c65..00000000 --- a/src/core/curl_socket.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef RTORRENT_CORE_CURL_SOCKET_H -#define RTORRENT_CORE_CURL_SOCKET_H - -#include -#include - -#include "globals.h" - -namespace core { - -class CurlStack; - -class CurlSocket : public torrent::Event { -public: - CurlSocket(int fd, CurlStack* stack) : m_stack(stack) { m_fileDesc = fd; } - ~CurlSocket(); - - const char* type_name() const { return "curl"; } - - void close(); - - static int receive_socket(void* easy_handle, curl_socket_t fd, int what, void* userp, void* socketp); - -private: - CurlSocket(const CurlSocket&); - void operator = (const CurlSocket&); - - virtual void event_read(); - virtual void event_write(); - virtual void event_error(); - - CurlStack* m_stack; -}; - -} - -#endif diff --git a/src/core/curl_stack.cc b/src/core/curl_stack.cc deleted file mode 100644 index 992931a7..00000000 --- a/src/core/curl_stack.cc +++ /dev/null @@ -1,243 +0,0 @@ -#include "config.h" - -#include -#include -#include - -#include "curl_get.h" -#include "curl_socket.h" -#include "curl_stack.h" - -namespace core { - -CurlStack::CurlStack() { - m_handle = (void*)curl_multi_init(); - m_task_timeout.slot() = std::bind(&CurlStack::receive_timeout, this); - -#if (LIBCURL_VERSION_NUM >= 0x071000) - curl_multi_setopt((CURLM*)m_handle, CURLMOPT_TIMERDATA, this); - curl_multi_setopt((CURLM*)m_handle, CURLMOPT_TIMERFUNCTION, &CurlStack::set_timeout); -#endif - curl_multi_setopt((CURLM*)m_handle, CURLMOPT_SOCKETDATA, this); - curl_multi_setopt((CURLM*)m_handle, CURLMOPT_SOCKETFUNCTION, &CurlSocket::receive_socket); -} - -CurlStack::~CurlStack() { - shutdown(); -} - -void -CurlStack::shutdown() { - if (!m_running) - return; - - m_running = false; - - while (!empty()) - front()->close(); - - curl_multi_cleanup((CURLM*)m_handle); - - torrent::this_thread::scheduler()->erase(&m_task_timeout); -} - -CurlGet* -CurlStack::new_object() { - return new CurlGet(this); -} - -CurlSocket* -CurlStack::new_socket(int fd) { - if (!m_running) - throw torrent::internal_error("CurlStack::new_socket() called when not running."); - - CurlSocket* socket = new CurlSocket(fd, this); - curl_multi_assign((CURLM*)m_handle, fd, socket); - return socket; -} - -void -CurlStack::receive_action(CurlSocket* socket, int events) { - CURLMcode code; - - do { - int count; -#if (LIBCURL_VERSION_NUM >= 0x071003) - code = curl_multi_socket_action((CURLM*)m_handle, - socket != NULL ? socket->file_descriptor() : CURL_SOCKET_TIMEOUT, - events, - &count); -#else - code = curl_multi_socket((CURLM*)m_handle, - socket != NULL ? socket->file_descriptor() : CURL_SOCKET_TIMEOUT, - &count); -#endif - - if (code > 0) - throw torrent::internal_error("Error calling curl_multi_socket_action."); - - // Socket might be removed when cleaning handles below, future - // calls should not use it. - socket = NULL; - events = 0; - - if ((unsigned int)count != size()) { - while (process_done_handle()) - ; // Do nothing. - - if (empty()) - torrent::this_thread::scheduler()->erase(&m_task_timeout); - } - - } while (code == CURLM_CALL_MULTI_PERFORM); -} - -bool -CurlStack::process_done_handle() { - int remaining_msgs = 0; - CURLMsg* msg = curl_multi_info_read((CURLM*)m_handle, &remaining_msgs); - - if (msg == NULL) - return false; - - if (msg->msg != CURLMSG_DONE) - throw torrent::internal_error("CurlStack::receive_action() msg->msg != CURLMSG_DONE."); - - if (msg->data.result == CURLE_COULDNT_RESOLVE_HOST) { - iterator itr = std::find_if(begin(), end(), [&msg](CurlGet* get) { return get->handle() == msg->easy_handle; }); - - if (itr == end()) - throw torrent::internal_error("Could not find CurlGet when calling CurlStack::receive_action."); - - if (!(*itr)->is_using_ipv6()) { - (*itr)->retry_ipv6(); - - if (curl_multi_add_handle((CURLM*)m_handle, (*itr)->handle()) > 0) - throw torrent::internal_error("Error calling curl_multi_add_handle."); - } - - } else { - transfer_done(msg->easy_handle, - msg->data.result == CURLE_OK ? NULL : curl_easy_strerror(msg->data.result)); - } - - return remaining_msgs != 0; -} - -void -CurlStack::transfer_done(void* handle, const char* msg) { - iterator itr = std::find_if(begin(), end(), [&handle](CurlGet* get) { return get->handle() == handle; }); - - if (itr == end()) - throw torrent::internal_error("Could not find CurlGet with the right easy_handle."); - - if (msg == NULL) - (*itr)->trigger_done(); - else - (*itr)->trigger_failed(msg); -} - -void -CurlStack::receive_timeout() { - receive_action(NULL, 0); - - if (!empty() && !m_task_timeout.is_scheduled()) { - // Sometimes libcurl forgets to reset the timeout. Try to poll the value in that case, or use 10 - // seconds max. - long timeout_ms; - curl_multi_timeout((CURLM*)m_handle, &timeout_ms); - - auto timeout = std::max(std::chrono::milliseconds(timeout_ms), 10s); - - torrent::this_thread::scheduler()->wait_for_ceil_seconds(&m_task_timeout, timeout); - } -} - -void -CurlStack::add_get(CurlGet* get) { - if (!m_user_agent.empty()) - curl_easy_setopt(get->handle(), CURLOPT_USERAGENT, m_user_agent.c_str()); - - if (!m_http_proxy.empty()) - curl_easy_setopt(get->handle(), CURLOPT_PROXY, m_http_proxy.c_str()); - - if (!m_bind_address.empty()) - curl_easy_setopt(get->handle(), CURLOPT_INTERFACE, m_bind_address.c_str()); - - if (!m_http_ca_path.empty()) - curl_easy_setopt(get->handle(), CURLOPT_CAPATH, m_http_ca_path.c_str()); - - if (!m_http_ca_cert.empty()) - curl_easy_setopt(get->handle(), CURLOPT_CAINFO, m_http_ca_cert.c_str()); - - curl_easy_setopt(get->handle(), CURLOPT_SSL_VERIFYHOST, (long)(m_ssl_verify_host ? 2 : 0)); - curl_easy_setopt(get->handle(), CURLOPT_SSL_VERIFYPEER, (long)(m_ssl_verify_peer ? 1 : 0)); - curl_easy_setopt(get->handle(), CURLOPT_DNS_CACHE_TIMEOUT, m_dns_timeout); - - base_type::push_back(get); - - if (m_active >= m_max_active) - return; - - m_active++; - get->set_active(true); - - if (curl_multi_add_handle((CURLM*)m_handle, get->handle()) > 0) - throw torrent::internal_error("Error calling curl_multi_add_handle."); - -#if (LIBCURL_VERSION_NUM < 0x071000) - receive_timeout(); -#endif -} - -void -CurlStack::remove_get(CurlGet* get) { - iterator itr = std::find(begin(), end(), get); - - if (itr == end()) - throw torrent::internal_error("Could not find CurlGet when calling CurlStack::remove."); - - base_type::erase(itr); - - // The CurlGet object was never activated, so we just skip this one. - if (!get->is_active()) - return; - - get->set_active(false); - - if (curl_multi_remove_handle((CURLM*)m_handle, get->handle()) > 0) - throw torrent::internal_error("Error calling curl_multi_remove_handle."); - - if (m_active == m_max_active && - (itr = std::find_if(begin(), end(), [](CurlGet* get) { return !get->is_active(); })) != end()) { - (*itr)->set_active(true); - - if (curl_multi_add_handle((CURLM*)m_handle, (*itr)->handle()) > 0) - throw torrent::internal_error("Error calling curl_multi_add_handle."); - - } else { - m_active--; - } -} - -void -CurlStack::global_init() { - curl_global_init(CURL_GLOBAL_ALL); -} - -void -CurlStack::global_cleanup() { - curl_global_cleanup(); -} - -// TODO: Is this function supposed to set a per-handle timeout, or is -// it the shortest timeout amongst all handles? -int -CurlStack::set_timeout([[maybe_unused]] void* handle, std::chrono::microseconds timeout, void* userp) { - CurlStack* stack = (CurlStack*)userp; - - torrent::this_thread::scheduler()->update_wait_for_ceil_seconds(&stack->m_task_timeout, timeout); - return 0; -} - -} diff --git a/src/core/curl_stack.h b/src/core/curl_stack.h deleted file mode 100644 index 71c96675..00000000 --- a/src/core/curl_stack.h +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef RTORRENT_CORE_CURL_STACK_H -#define RTORRENT_CORE_CURL_STACK_H - -#include -#include -#include - -namespace core { - -class CurlGet; -class CurlSocket; - -// By using a deque instead of vector we allow for cheaper removal of -// the oldest elements, those that will be first in the in the -// deque. -// -// This should fit well with the use-case of a http stack, thus -// we get most of the cache locality benefits of a vector with fast -// removal of elements. - -class CurlStack : std::deque { -public: - friend class CurlGet; - - typedef std::deque base_type; - - using base_type::value_type; - using base_type::iterator; - using base_type::const_iterator; - using base_type::reverse_iterator; - using base_type::const_reverse_iterator; - - using base_type::begin; - using base_type::end; - using base_type::rbegin; - using base_type::rend; - - using base_type::back; - using base_type::front; - - using base_type::size; - using base_type::empty; - - CurlStack(); - ~CurlStack(); - - void shutdown(); - bool is_running() const { return m_running; } - - CurlGet* new_object(); - CurlSocket* new_socket(int fd); - - unsigned int active() const { return m_active; } - unsigned int max_active() const { return m_max_active; } - void set_max_active(unsigned int a) { m_max_active = a; } - - const std::string& user_agent() const { return m_user_agent; } - const std::string& http_proxy() const { return m_http_proxy; } - const std::string& bind_address() const { return m_bind_address; } - const std::string& http_capath() const { return m_http_ca_path; } - const std::string& http_cacert() const { return m_http_ca_cert; } - - void set_user_agent(const std::string& s) { m_user_agent = s; } - void set_http_proxy(const std::string& s) { m_http_proxy = s; } - void set_bind_address(const std::string& s) { m_bind_address = s; } - void set_http_capath(const std::string& s) { m_http_ca_path = s; } - void set_http_cacert(const std::string& s) { m_http_ca_cert = s; } - - bool ssl_verify_host() const { return m_ssl_verify_host; } - bool ssl_verify_peer() const { return m_ssl_verify_peer; } - void set_ssl_verify_host(bool s) { m_ssl_verify_host = s; } - void set_ssl_verify_peer(bool s) { m_ssl_verify_peer = s; } - - long dns_timeout() const { return m_dns_timeout; } - void set_dns_timeout(long timeout) { m_dns_timeout = timeout; } - - static void global_init(); - static void global_cleanup(); - - void receive_action(CurlSocket* socket, int type); - - static int set_timeout(void* handle, std::chrono::microseconds timeout, void* userp); - - void transfer_done(void* handle, const char* msg); - -protected: - void add_get(CurlGet* get); - void remove_get(CurlGet* get); - -private: - CurlStack(const CurlStack&) = delete; - void operator = (const CurlStack&) = delete; - - void receive_timeout(); - - bool process_done_handle(); - - void* m_handle; - - bool m_running{true}; - - unsigned int m_active{0}; - unsigned int m_max_active{32}; - - torrent::utils::SchedulerEntry m_task_timeout; - - std::string m_user_agent; - std::string m_http_proxy; - std::string m_bind_address; - std::string m_http_ca_path; - std::string m_http_ca_cert; - - bool m_ssl_verify_host{true}; - bool m_ssl_verify_peer{true}; - long m_dns_timeout{60}; -}; - -} - -#endif diff --git a/src/core/download_factory.cc b/src/core/download_factory.cc index ee44c909..72080c4e 100644 --- a/src/core/download_factory.cc +++ b/src/core/download_factory.cc @@ -1,11 +1,12 @@ #include "config.h" +#include "download_factory.h" + #include #include #include #include #include - #include #include #include @@ -14,18 +15,15 @@ #include #include #include +#include -#include "rpc/parse_commands.h" - -#include "curl_get.h" #include "control.h" -#include "http_queue.h" #include "globals.h" -#include "manager.h" - -#include "download.h" -#include "download_factory.h" -#include "download_store.h" +#include "core/download.h" +#include "core/download_store.h" +#include "core/http_queue.h" +#include "core/manager.h" +#include "rpc/parse_commands.h" namespace core { @@ -111,10 +109,11 @@ DownloadFactory::receive_load() { if (is_network_uri(m_uri)) { // Http handling here. m_stream = new std::stringstream; + HttpQueue::iterator itr = m_manager->http_queue()->insert(m_uri, m_stream); - (*itr)->signal_done().push_front(std::bind(&DownloadFactory::receive_loaded, this)); - (*itr)->signal_failed().push_front(std::bind(&DownloadFactory::receive_failed, this, std::placeholders::_1)); + itr->add_done_slot([this]() { receive_loaded(); }); + itr->add_failed_slot([this](const std::string& error) { receive_failed(error); }); m_variables["tied_to_file"] = (int64_t)false; diff --git a/src/core/http_queue.cc b/src/core/http_queue.cc index 4e1fc460..0f694982 100644 --- a/src/core/http_queue.cc +++ b/src/core/http_queue.cc @@ -1,43 +1,32 @@ #include "config.h" -#include -#include -#include - #include "http_queue.h" -#include "curl_get.h" + +#include +#include namespace core { HttpQueue::iterator HttpQueue::insert(const std::string& url, std::iostream* s) { - std::unique_ptr h(m_slot_factory()); + auto itr = base_type::insert(end(), torrent::net_thread::http_stack()->create(url, s)); - h->set_url(url); - h->set_stream(s); - h->set_timeout(5 * 60); + itr->add_done_slot([this, itr]() { erase(itr); }); + itr->add_failed_slot([this, itr](auto) { erase(itr); }); - iterator signal_itr = base_type::insert(end(), h.get()); + itr->start(); - h->signal_done().push_back(std::bind(&HttpQueue::erase, this, signal_itr)); - h->signal_failed().push_back(std::bind(&HttpQueue::erase, this, signal_itr)); + for (auto& slot : m_signal_insert) + slot(*itr); - (*signal_itr)->start(); - - h.release(); - - for (signal_curl_get::iterator itr = m_signal_insert.begin(), last = m_signal_insert.end(); itr != last; itr++) - (*itr)(*signal_itr); - - return signal_itr; + return itr; } void HttpQueue::erase(iterator signal_itr) { - for (signal_curl_get::iterator itr = m_signal_erase.begin(), last = m_signal_erase.end(); itr != last; itr++) - (*itr)(*signal_itr); + for (const auto& slot : m_signal_erase) + slot(*signal_itr); - delete *signal_itr; base_type::erase(signal_itr); } @@ -45,8 +34,6 @@ void HttpQueue::clear() { while (!empty()) erase(begin()); - - base_type::clear(); } } diff --git a/src/core/http_queue.h b/src/core/http_queue.h index a39fffd4..93a98945 100644 --- a/src/core/http_queue.h +++ b/src/core/http_queue.h @@ -4,17 +4,18 @@ #include #include #include +#include +#include namespace core { -class CurlGet; +// TODO: Remove this. -class HttpQueue : private std::list { +class HttpQueue : private std::list { public: - typedef std::list base_type; - typedef std::function slot_factory; - typedef std::function slot_curl_get; - typedef std::list signal_curl_get; + using base_type = std::list; + using slot_curl_get = std::function; + using signal_curl_get = std::list; using base_type::iterator; using base_type::const_iterator; @@ -42,13 +43,10 @@ public: void clear(); - void set_slot_factory(slot_factory s) { m_slot_factory = s; } - signal_curl_get& signal_insert() { return m_signal_insert; } signal_curl_get& signal_erase() { return m_signal_erase; } private: - slot_factory m_slot_factory; signal_curl_get m_signal_insert; signal_curl_get m_signal_erase; }; diff --git a/src/core/manager.cc b/src/core/manager.cc index d77ccf6a..176ddba6 100644 --- a/src/core/manager.cc +++ b/src/core/manager.cc @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "rpc/parse_commands.h" @@ -26,15 +27,13 @@ #include "utils/file_status_cache.h" #include "globals.h" -#include "curl_get.h" -#include "curl_stack.h" #include "control.h" -#include "download.h" -#include "download_factory.h" -#include "download_store.h" -#include "http_queue.h" -#include "manager.h" -#include "view.h" +#include "core/download.h" +#include "core/download_factory.h" +#include "core/download_store.h" +#include "core/http_queue.h" +#include "core/manager.h" +#include "core/view.h" namespace core { @@ -57,7 +56,6 @@ Manager::Manager() : m_download_list = std::make_unique(); m_file_status_cache = std::make_unique(); m_http_queue = std::make_unique(); - m_http_stack = std::make_unique(); torrent::Throttle* unthrottled = torrent::Throttle::create_throttle(); unthrottled->set_max_rate(0); @@ -131,31 +129,14 @@ Manager::retrieve_throttle_value(const torrent::Object::string_type& name, bool } } -// Most of this should be possible to move out. -void -Manager::initialize_second() { - torrent::Http::slot_factory() = std::bind(&CurlStack::new_object, m_http_stack.get()); - m_http_queue->set_slot_factory(std::bind(&CurlStack::new_object, m_http_stack.get())); - - CurlStack::global_init(); -} - void Manager::cleanup() { - m_http_stack->shutdown(); - // Need to disconnect log signals? Not really since we won't receive // any more. m_download_list->clear(); - // When we implement asynchronous DNS lookups, we need to cancel them - // here before the torrent::* objects are deleted. - torrent::cleanup(); - - m_http_stack.reset(); - CurlStack::global_cleanup(); } void @@ -229,7 +210,10 @@ Manager::set_bind_address(const std::string& addr) { torrent::connection_manager()->set_bind_address(ai->address()->c_sockaddr()); } - m_http_stack->set_bind_address(!ai->address()->is_address_any() ? ai->address()->address_str() : std::string()); + if (ai->address()->is_address_any()) + torrent::net_thread::http_stack()->set_bind_address(std::string()); + else + torrent::net_thread::http_stack()->set_bind_address(ai->address()->address_str()); rak::address_info::free_address_info(ai); diff --git a/src/core/manager.h b/src/core/manager.h index 065e9c93..161b98d3 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -21,7 +21,6 @@ class FileStatusCache; namespace core { -class CurlStack; class DownloadStore; class HttpQueue; @@ -42,7 +41,6 @@ public: FileStatusCache* file_status_cache() { return m_file_status_cache.get(); } HttpQueue* http_queue() { return m_http_queue.get(); } - CurlStack* http_stack() { return m_http_stack.get(); } View* hashing_view() { return m_hashingView; } void set_hashing_view(View* v); @@ -59,8 +57,6 @@ public: void set_address_throttle(uint32_t begin, uint32_t end, torrent::ThrottlePair throttles); torrent::ThrottlePair get_address_throttle(const sockaddr* addr); - // Really should find a more descriptive name. - void initialize_second(); void cleanup(); void listen_open(); @@ -109,7 +105,6 @@ private: std::unique_ptr m_download_store; std::unique_ptr m_file_status_cache; std::unique_ptr m_http_queue; - std::unique_ptr m_http_stack; View* m_hashingView{}; diff --git a/src/display/utils.cc b/src/display/utils.cc index c3ba9bb5..c3c03b4b 100644 --- a/src/display/utils.cc +++ b/src/display/utils.cc @@ -1,5 +1,7 @@ #include "config.h" +#include "display/utils.h" + #include #include #include @@ -14,18 +16,16 @@ #include #include #include +#include #include -#include "core/curl_stack.h" +#include "control.h" +#include "globals.h" #include "core/download.h" #include "core/manager.h" #include "rpc/parse_commands.h" #include "ui/root.h" -#include "control.h" -#include "globals.h" -#include "utils.h" - namespace display { char* @@ -111,7 +111,7 @@ print_download_info_full(char* first, char* last, core::Download* d) { first = print_buffer(first, last, "%6.1f / %6.1f MB", (double)d->download()->bytes_done() / (double)(1 << 20), (double)d->download()->file_list()->size_bytes() / (double)(1 << 20)); - + first = print_buffer(first, last, " Rate: %5.1f / %5.1f KB Uploaded: %7.1f MB", (double)d->info()->up_rate()->rate() / (1 << 10), (double)d->info()->down_rate()->rate() / (1 << 10), @@ -391,7 +391,7 @@ print_status_info(char* first, char* last) { first = print_address(first, last, torrent::connection_manager()->local_address()); first = print_buffer(first, last, "]"); } - + if (first > last) throw torrent::internal_error("print_status_info(...) wrote past end of the buffer."); @@ -415,14 +415,14 @@ print_status_extra(char* first, char* last) { torrent::resource_manager()->max_download_unchoked()); first = print_buffer(first, last, " [H %u/%u]", - control->core()->http_stack()->active(), - control->core()->http_stack()->max_active()); + torrent::net_thread::http_stack()->active(), + torrent::net_thread::http_stack()->max_active()); first = print_buffer(first, last, " [S %i/%i/%i]", torrent::total_handshakes(), torrent::connection_manager()->size(), torrent::connection_manager()->max_size()); - + first = print_buffer(first, last, " [F %i/%i]", torrent::file_manager()->open_files(), torrent::file_manager()->max_open_files()); diff --git a/src/display/utils.h b/src/display/utils.h index 66468779..69d89281 100644 --- a/src/display/utils.h +++ b/src/display/utils.h @@ -1,45 +1,10 @@ -// rTorrent - BitTorrent client -// Copyright (C) 2005-2011, Jari Sundell -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// In addition, as a special exception, the copyright holders give -// permission to link the code of portions of this program with the -// OpenSSL library under certain conditions as described in each -// individual source file, and distribute linked combinations -// including the two. -// -// You must obey the GNU General Public License in all respects for -// all of the code used other than OpenSSL. If you modify file(s) -// with this exception, you may extend this exception to your version -// of the file(s), but you are not obligated to do so. If you do not -// wish to do so, delete this exception statement from your version. -// If you delete this exception statement from all source files in the -// program, then also delete it here. -// -// Contact: Jari Sundell -// -// Skomakerveien 33 -// 3185 Skoppum, NORWAY - #ifndef RTORRENT_DISPLAY_UTILS_H #define RTORRENT_DISPLAY_UTILS_H #include #include #include +#include namespace core { class Download; diff --git a/src/display/window_http_queue.cc b/src/display/window_http_queue.cc index 9af81fcc..df34026d 100644 --- a/src/display/window_http_queue.cc +++ b/src/display/window_http_queue.cc @@ -3,8 +3,8 @@ #include "display/window_http_queue.h" #include +#include -#include "core/curl_get.h" #include "core/http_queue.h" #include "display/canvas.h" @@ -17,8 +17,9 @@ WindowHttpQueue::WindowHttpQueue(core::HttpQueue* q) : m_queue(q) { set_active(false); - m_conn_insert = m_queue->signal_insert().insert(m_queue->signal_insert().end(), [this](auto* h) { receive_insert(h); }); - m_conn_erase = m_queue->signal_erase().insert(m_queue->signal_insert().end(), [this](auto* h) { receive_erase(h); }); + + m_conn_insert = m_queue->signal_insert().insert(m_queue->signal_insert().end(), [this](auto h) { receive_insert(h); }); + m_conn_erase = m_queue->signal_erase().insert(m_queue->signal_insert().end(), [this](auto h) { receive_erase(h); }); m_task_deactivate.slot() = [this] { if (!m_container.empty()) @@ -55,14 +56,14 @@ WindowHttpQueue::redraw() { Container::iterator itr = m_container.begin(); while (itr != m_container.end() && pos + 10 < m_canvas->width()) { - if (itr->m_http == NULL) + if (!itr->m_http.is_valid()) m_canvas->print(pos, 0, "[%s done]", itr->m_name.c_str()); - else if (itr->m_http->size_total() == 0) + else if (itr->m_http.size_total() == 0) m_canvas->print(pos, 0, "[%s ---%%]", itr->m_name.c_str()); else - m_canvas->print(pos, 0, "[%s %3i%%]", itr->m_name.c_str(), (int)(100.0 * itr->m_http->size_done() / itr->m_http->size_total())); + m_canvas->print(pos, 0, "[%s %3i%%]", itr->m_name.c_str(), (int)(100.0 * itr->m_http.size_done() / itr->m_http.size_total())); pos += itr->m_name.size() + 6; ++itr; @@ -72,7 +73,7 @@ WindowHttpQueue::redraw() { void WindowHttpQueue::cleanup_list() { for (Container::iterator itr = m_container.begin(); itr != m_container.end(); ) { - if (itr->m_http == nullptr && itr->m_timer < torrent::this_thread::cached_time()) { + if (!itr->m_http.is_valid() && itr->m_timer < torrent::this_thread::cached_time()) { itr = m_container.erase(itr); continue; } @@ -82,10 +83,10 @@ WindowHttpQueue::cleanup_list() { } std::string -WindowHttpQueue::create_name(core::CurlGet* h) { - size_t p = h->url().rfind('/', h->url().size() - std::min(10, h->url().size())); +WindowHttpQueue::create_name(torrent::net::HttpGet http_get) { + size_t p = http_get.url().rfind('/', http_get.url().size() - std::min(10, http_get.url().size())); - std::string n = p != std::string::npos ? h->url().substr(p) : h->url(); + std::string n = p != std::string::npos ? http_get.url().substr(p) : http_get.url(); if (n.empty()) throw std::logic_error("WindowHttpQueue::create_name(...) made a bad string"); @@ -105,8 +106,8 @@ WindowHttpQueue::create_name(core::CurlGet* h) { } void -WindowHttpQueue::receive_insert(core::CurlGet* h) { - m_container.push_back(Node(h, create_name(h))); +WindowHttpQueue::receive_insert(torrent::net::HttpGet http_get) { + m_container.push_back(Node(http_get, create_name(http_get))); if (!is_active()) { set_active(true); @@ -117,8 +118,10 @@ WindowHttpQueue::receive_insert(core::CurlGet* h) { } void -WindowHttpQueue::receive_erase(core::CurlGet* h) { - Container::iterator itr = std::find_if(m_container.begin(), m_container.end(), [h](Node& n) { return h == n.m_http; }); +WindowHttpQueue::receive_erase(torrent::net::HttpGet http_get) { + Container::iterator itr = std::find_if(m_container.begin(), + m_container.end(), + [http_get](Node& n) { return http_get == n.m_http; }); if (itr == m_container.end()) throw std::logic_error("WindowHttpQueue::receive_erase(...) tried to remove an object we don't have"); diff --git a/src/display/window_http_queue.h b/src/display/window_http_queue.h index ba9d1df8..1fd46043 100644 --- a/src/display/window_http_queue.h +++ b/src/display/window_http_queue.h @@ -3,20 +3,20 @@ #include #include +#include #include "window.h" namespace core { - class CurlGet; - class HttpQueue; +class HttpQueue; } namespace display { class WindowHttpQueue : public Window { public: - typedef std::function slot_curl_get; - typedef std::list signal_curl_get; + typedef std::function slot_curl_get; + typedef std::list signal_curl_get; WindowHttpQueue(core::HttpQueue* q); ~WindowHttpQueue() override; @@ -25,9 +25,9 @@ public: private: struct Node { - Node(core::CurlGet* h, const std::string& n) : m_http(h), m_name(n) {} + Node(torrent::net::HttpGet h, const std::string& n) : m_http(h), m_name(n) {} - core::CurlGet* m_http{}; + torrent::net::HttpGet m_http{}; std::string m_name; std::chrono::microseconds m_timer{}; }; @@ -36,10 +36,10 @@ private: void cleanup_list(); - void receive_insert(core::CurlGet* h); - void receive_erase(core::CurlGet* h); + void receive_insert(torrent::net::HttpGet h); + void receive_erase(torrent::net::HttpGet h); - static std::string create_name(core::CurlGet* h); + static std::string create_name(torrent::net::HttpGet h); core::HttpQueue* m_queue; Container m_container; diff --git a/src/main.cc b/src/main.cc index b04285b5..db22e421 100644 --- a/src/main.cc +++ b/src/main.cc @@ -7,8 +7,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -454,8 +454,10 @@ main(int argc, char** argv) { } catch (torrent::internal_error& e) { control->cleanup_exception(); - std::cout << "Caught internal_error: " << e.what() << std::endl + std::cout << "rtorrent: caught torrent::internal_error: " + << e.what() << std::endl << e.backtrace(); + lt_log_print_dump(torrent::LOG_CRITICAL, e.backtrace().c_str(), e.backtrace().size(), "Caught internal_error: '%s'.", e.what()); return -1; @@ -463,7 +465,8 @@ main(int argc, char** argv) { } catch (std::exception& e) { control->cleanup_exception(); - std::cout << "rtorrent: " << e.what() << std::endl; + std::cout << "rtorrent: caught" << typeid(e).name() << " : " << e.what() << std::endl; + lt_log_print(torrent::LOG_CRITICAL, "Caught exception: '%s'.", e.what()); return -1; }