From d35a8d68e6395313b13b665d95a7421d7faaec28 Mon Sep 17 00:00:00 2001 From: Jari Sundell Date: Mon, 25 Aug 2025 08:56:15 +0200 Subject: [PATCH] Fixed uninitialized rpc slots when SCGI is not used. --- src/command_network.cc | 34 ++++------------------------------ src/core/dht_manager.cc | 4 ++-- src/main.cc | 31 +++++++++++++++++++++++++++++++ src/rpc/command_map.cc | 8 ++++---- src/rpc/rpc_manager.cc | 21 +++++++++++++-------- src/rpc/rpc_manager.h | 26 ++++++++++++++------------ 6 files changed, 68 insertions(+), 56 deletions(-) diff --git a/src/command_network.cc b/src/command_network.cc index 336d2522..8d3168fe 100644 --- a/src/command_network.cc +++ b/src/command_network.cc @@ -59,34 +59,8 @@ apply_tos(const torrent::Object::string_type& arg) { torrent::Object apply_encoding_list(const std::string& arg) { torrent::encoding_list()->push_back(arg); return torrent::Object(); } void -initialize_rpc() { - rpc::rpc.initialize(); - - rpc::rpc.slot_find_download() = [](const char* hash) { - return control->core()->download_list()->find_hex_ptr(hash); - }; - rpc::rpc.slot_find_file() = [](core::Download* d, uint32_t index) -> torrent::File* { - if (index >= d->file_list()->size_files()) - throw torrent::input_error("invalid parameters: index not found"); - - return (*d->file_list())[index].get(); - }; - rpc::rpc.slot_find_tracker() = [](core::Download* d, uint32_t index) -> torrent::tracker::Tracker { - if (index >= d->tracker_controller().size()) - throw torrent::input_error("invalid parameters: index not found"); - - // TODO: This should be rewritten to check if the tracker is valid and use a different - // function. - return d->tracker_controller().at(index); - }; - rpc::rpc.slot_find_peer() = [](core::Download* d, const torrent::HashString& hash) -> torrent::Peer* { - auto itr = d->connection_list()->find(hash.c_str()); - - if (itr == d->connection_list()->end()) - throw torrent::input_error("invalid parameters: hash not found"); - - return *itr; - }; +initialize_rpc_handlers() { + rpc::rpc.initialize_handlers(); unsigned int count = 0; @@ -98,7 +72,7 @@ initialize_rpc() { ++count; } - lt_log_print(torrent::LOG_RPC_EVENTS, "RPC initialized with %u functions.", count); + lt_log_print(torrent::LOG_RPC_EVENTS, "RPC manager initialized with %u functions.", count); } torrent::Object @@ -106,7 +80,7 @@ apply_scgi(const std::string& arg, int type) { if (worker_thread->scgi() != NULL) throw torrent::input_error("SCGI already enabled."); - initialize_rpc(); + initialize_rpc_handlers(); rpc::SCgi* scgi = new rpc::SCgi; diff --git a/src/core/dht_manager.cc b/src/core/dht_manager.cc index f280cee3..ec38a800 100644 --- a/src/core/dht_manager.cc +++ b/src/core/dht_manager.cc @@ -82,12 +82,12 @@ DhtManager::start_dht() { torrent::this_thread::scheduler()->erase(&m_stop_timeout); if (!torrent::dht_controller()->is_valid()) { - LT_LOG_ERROR("server start skipped, manager is uninitialized", 0); + LT_LOG("server start skipped, manager is uninitialized", 0); return; } if (torrent::dht_controller()->is_active()) { - LT_LOG_ERROR("server start skipped, already active", 0); + LT_LOG("server start skipped, already active", 0); return; } diff --git a/src/main.cc b/src/main.cc index a7185ad5..80bca3a6 100644 --- a/src/main.cc +++ b/src/main.cc @@ -83,6 +83,35 @@ parse_options(int argc, char** argv) { } } +void +initialize_rpc_slots() { + rpc::rpc.slot_find_download() = [](const char* hash) { + return control->core()->download_list()->find_hex_ptr(hash); + }; + rpc::rpc.slot_find_file() = [](core::Download* d, uint32_t index) -> torrent::File* { + if (index >= d->file_list()->size_files()) + throw torrent::input_error("invalid parameters: index not found"); + + return (*d->file_list())[index].get(); + }; + rpc::rpc.slot_find_tracker() = [](core::Download* d, uint32_t index) -> torrent::tracker::Tracker { + if (index >= d->tracker_controller().size()) + throw torrent::input_error("invalid parameters: index not found"); + + // TODO: This should be rewritten to check if the tracker is valid and use a different + // function. + return d->tracker_controller().at(index); + }; + rpc::rpc.slot_find_peer() = [](core::Download* d, const torrent::HashString& hash) -> torrent::Peer* { + auto itr = d->connection_list()->find(hash.c_str()); + + if (itr == d->connection_list()->end()) + throw torrent::input_error("invalid parameters: hash not found"); + + return *itr; + }; +} + void load_session_torrents() { utils::Directory entries = control->core()->download_store()->get_formated_entries(); @@ -182,6 +211,8 @@ main(int argc, char** argv) { torrent::log_add_group_output(torrent::LOG_DHT_ERROR, "complete"); torrent::log_add_group_output(torrent::LOG_DHT_CONTROLLER, "complete"); + initialize_rpc_slots(); + torrent::initialize(); torrent::set_main_thread_slots(std::bind(&client_perform)); diff --git a/src/rpc/command_map.cc b/src/rpc/command_map.cc index 32a3a212..ff4d6e3d 100644 --- a/src/rpc/command_map.cc +++ b/src/rpc/command_map.cc @@ -27,7 +27,7 @@ CommandMap::insert(const key_type& key, int flags, const char* parm, const char* throw torrent::internal_error("CommandMap::insert(...) tried to insert an already existing key."); // TODO: This is not honoring the public_xmlrpc flags!!! - if (rpc::rpc.is_initialized() && (flags & flag_public_rpc)) + if (rpc::rpc.is_handlers_initialized() && (flags & flag_public_rpc)) rpc::rpc.insert_command(key.c_str(), parm, doc); return base_type::insert(itr, value_type(key, command_map_data_type(flags, parm, doc))); @@ -55,10 +55,10 @@ CommandMap::create_redirect(const key_type& key_new, const key_type& key_dest, i if (dest_itr == base_type::end()) throw torrent::input_error("Tried to redirect to a key that doesn't exist: '" + std::string(key_dest) + "'."); - + if (new_itr != base_type::end()) throw torrent::input_error("Tried to create a redirect key that already exists: '" + std::string(key_new) + "'."); - + if (dest_itr->second.m_flags & flag_is_redirect) throw torrent::input_error("Tried to redirect to a key that is not marked 'flag_is_redirect': '" + std::string(key_dest) + "'."); @@ -68,7 +68,7 @@ CommandMap::create_redirect(const key_type& key_new, const key_type& key_dest, i flags |= dest_itr->second.m_flags & ~(flag_has_redirects | flag_public_rpc); // TODO: This is not honoring the public_xmlrpc flags!!! - if (rpc::rpc.is_initialized() && (flags & flag_public_rpc)) + if (rpc::rpc.is_handlers_initialized() && (flags & flag_public_rpc)) rpc::rpc.insert_command(key_new.c_str(), dest_itr->second.m_parm, dest_itr->second.m_doc); iterator itr = base_type::insert(base_type::end(), diff --git a/src/rpc/rpc_manager.cc b/src/rpc/rpc_manager.cc index 7419f8b5..3017a141 100644 --- a/src/rpc/rpc_manager.cc +++ b/src/rpc/rpc_manager.cc @@ -21,8 +21,10 @@ RpcManager::object_to_target(const torrent::Object& obj, int call_flags, rpc::ta if (!obj.is_string()) { throw torrent::input_error("invalid parameters: target must be a string"); } + std::string target_string = obj.as_string(); bool require_index = (call_flags & (CommandMap::flag_tracker_target | CommandMap::flag_file_target)); + if (target_string.size() == 0 && !require_index) { return; } @@ -37,24 +39,27 @@ RpcManager::object_to_target(const torrent::Object& obj, int call_flags, rpc::ta std::string index; const auto& delim_pos = target_string.find_first_of(':', 40); + if (delim_pos == target_string.npos || delim_pos + 2 >= target_string.size()) { if (require_index) { throw torrent::input_error("invalid parameters: no index"); } hash = target_string; + } else { hash = target_string.substr(0, delim_pos); type = target_string[delim_pos + 1]; index = target_string.substr(delim_pos + 2); } + core::Download* download = rpc.slot_find_download()(hash.c_str()); if (download == nullptr) throw torrent::input_error("invalid parameters: info-hash not found"); try { - torrent::tracker::Tracker* tracker; + torrent::tracker::Tracker* tracker{}; switch (type) { case 'd': @@ -126,15 +131,20 @@ RpcManager::process(RPCType type, const char* in_buffer, uint32_t length, slot_r } void -RpcManager::initialize() { +RpcManager::initialize_handlers() { + if (m_handlers_initialized) + throw torrent::internal_error("handlers already initialized"); + m_xmlrpc.initialize(); m_jsonrpc.initialize(); - m_initialized = true; + m_handlers_initialized = true; } void RpcManager::cleanup() { + m_handlers_initialized = false; + m_xmlrpc.cleanup(); m_jsonrpc.cleanup(); } @@ -165,11 +175,6 @@ RpcManager::set_type_enabled(RPCType type, bool enabled) { } } -bool -RpcManager::is_initialized() const { - return m_initialized; -} - void RpcManager::insert_command(const char* name, const char* parm, const char* doc) { m_xmlrpc.insert_command(name, parm, doc); diff --git a/src/rpc/rpc_manager.h b/src/rpc/rpc_manager.h index 36061583..17bccafb 100644 --- a/src/rpc/rpc_manager.h +++ b/src/rpc/rpc_manager.h @@ -48,14 +48,16 @@ public: RpcManager() = default; ~RpcManager() = default; - void initialize(); - void cleanup(); - bool is_initialized() const; + bool is_handlers_initialized() const { return m_handlers_initialized; } - int64_t size_limit() { return m_xmlrpc.size_limit(); }; + void initialize_handlers(); + void cleanup(); + + int64_t size_limit() { return m_xmlrpc.size_limit(); }; void set_size_limit(uint64_t size) { m_xmlrpc.set_size_limit(size); }; - int dialect() { return m_xmlrpc.dialect(); } - void set_dialect(int dialect) { m_xmlrpc.set_dialect(dialect); } + + int dialect() { return m_xmlrpc.dialect(); } + void set_dialect(int dialect) { m_xmlrpc.set_dialect(dialect); } bool is_type_enabled(RPCType type) const; void set_type_enabled(RPCType type, bool enabled); @@ -65,9 +67,9 @@ public: void insert_command(const char* name, const char* parm, const char* doc); slot_download& slot_find_download() { return m_slot_find_download; } - slot_file& slot_find_file() { return m_slot_find_file; } - slot_tracker& slot_find_tracker() { return m_slot_find_tracker; } - slot_peer& slot_find_peer() { return m_slot_find_peer; } + slot_file& slot_find_file() { return m_slot_find_file; } + slot_tracker& slot_find_tracker() { return m_slot_find_tracker; } + slot_peer& slot_find_peer() { return m_slot_find_peer; } static void object_to_target(const torrent::Object& obj, int callFlags, rpc::target_type* target, std::function* deleter); @@ -75,9 +77,9 @@ private: XmlRpc m_xmlrpc; JsonRpc m_jsonrpc; - bool m_initialized = false; - bool m_is_jsonrpc_enabled = true; - bool m_is_xmlrpc_enabled = true; + bool m_handlers_initialized{}; + bool m_is_jsonrpc_enabled{true}; + bool m_is_xmlrpc_enabled{true}; slot_download m_slot_find_download; slot_file m_slot_find_file;