From 3fec14f95e2ae69bbfe7c436d338a0ba8233d873 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 24 May 2023 23:43:44 +0200 Subject: [PATCH] Implemented multiple map rpc processing(lets chain RPC processing to different handlers maps in different objects) --- .../include/net/http_server_handlers_map2.h | 27 ++++++++++ contrib/epee/include/sync_locked_object.h | 2 + src/rpc/core_rpc_server.h | 4 ++ src/wallet/wallet_rpc_server.cpp | 5 +- src/wallet/wallet_rpc_server.h | 18 ++++--- src/wallet/wallets_manager.cpp | 49 ++++++++++++++++++- src/wallet/wallets_manager.h | 26 +++++++++- 7 files changed, 118 insertions(+), 13 deletions(-) diff --git a/contrib/epee/include/net/http_server_handlers_map2.h b/contrib/epee/include/net/http_server_handlers_map2.h index 6b45950a..5f002c42 100644 --- a/contrib/epee/include/net/http_server_handlers_map2.h +++ b/contrib/epee/include/net/http_server_handlers_map2.h @@ -29,6 +29,7 @@ #include "serialization/keyvalue_serialization.h" #include "storages/portable_storage_template_helper.h" #include "http_base.h" +#include "net/net_utils_base.h" template bool auto_doc_t(const std::string& prefix_name, std::string& generate_reference) @@ -51,6 +52,20 @@ bool auto_doc(const std::string& prefix_name, std::string& generate_reference) return auto_doc_t(prefix_name, generate_reference); } +namespace epee { + namespace net_utils { + namespace http { + struct i_chain_handler + { + virtual bool handle_http_request_map(const epee::net_utils::http::http_request_info& query_info, epee::net_utils::http::http_response_info& response_info, + epee::net_utils::connection_context_base& m_conn_context, bool& call_found, std::string& generate_reference) = 0; + }; + } + } +} + + + #define CHAIN_HTTP_TO_MAP2(context_type) bool handle_http_request(const epee::net_utils::http::http_request_info& query_info, \ epee::net_utils::http::http_response_info& response, \ @@ -73,6 +88,13 @@ bool auto_doc(const std::string& prefix_name, std::string& generate_reference) call_found = false; \ if(false) return true; //just a stub to have "else if" +#define BEGIN_URI_MAP2_VIRTUAL() virtual bool handle_http_request_map(const epee::net_utils::http::http_request_info& query_info, \ + epee::net_utils::http::http_response_info& response_info, \ + epee::net_utils::connection_context_base& m_conn_context, bool& call_found, std::string& generate_reference) { \ + call_found = false; \ + if(false) return true; //just a stub to have "else if" + + #define MAP_URI2(pattern, callback) else if(std::string::npos != query_info.m_URI.find(pattern)) return callback(query_info, response_info, m_conn_context); #define MAP_URI_AUTO_XML2(s_pattern, callback_f, command_type) //TODO: don't think i ever again will use xml - ambiguous and "overtagged" format @@ -117,6 +139,8 @@ bool auto_doc(const std::string& prefix_name, std::string& generate_reference) LOG_PRINT( "[HTTP/BIN][" << epee::string_tools::get_ip_string_from_int32(m_conn_context.m_remote_ip ) << "][" << query_info.m_URI << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2); \ } +#define CHAIN_TO_PHANDLER(pi_chain_handler) else if (pi_chain_handler && pi_chain_handler->handle_http_request_map(query_info, response_info, m_conn_context, call_found, generate_reference) && call_found) { return true;} + #define CHAIN_URI_MAP2(callback) else {callback(query_info, response_info, m_conn_context);call_found = true;} #define END_URI_MAP2() return true;} @@ -287,6 +311,7 @@ struct json_command_type_t #define MAP_JON_RPC_WE(method_name, callback_f, command_type) \ else if(auto_doc>("[" method_name "]", generate_reference) && callback_name == method_name) \ { \ + call_found = true; \ PREPARE_OBJECTS_FROM_JSON(command_type) \ epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ fail_resp.jsonrpc = "2.0"; \ @@ -304,6 +329,7 @@ struct json_command_type_t #define MAP_JON_RPC_WERI(method_name, callback_f, command_type) \ else if(auto_doc>("[" method_name "]", generate_reference) && callback_name == method_name) \ { \ + call_found = true; \ PREPARE_OBJECTS_FROM_JSON(command_type) \ epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ fail_resp.jsonrpc = "2.0"; \ @@ -321,6 +347,7 @@ struct json_command_type_t #define MAP_JON_RPC(method_name, callback_f, command_type) \ else if(auto_doc>(std::string("[") + method_name + "]", generate_reference) && callback_name == method_name) \ { \ + call_found = true; \ PREPARE_OBJECTS_FROM_JSON(command_type) \ if(!callback_f(req.params, resp.result, m_conn_context)) \ { \ diff --git a/contrib/epee/include/sync_locked_object.h b/contrib/epee/include/sync_locked_object.h index 2980bbb7..aa01e110 100644 --- a/contrib/epee/include/sync_locked_object.h +++ b/contrib/epee/include/sync_locked_object.h @@ -84,6 +84,8 @@ namespace epee template friend class locked_object_proxy; public: + typedef std::shared_ptr> lock_shared_ptr; + std::shared_ptr> lock() { std::shared_ptr> res; diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index 4e52d22d..f6cf669c 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -37,6 +37,7 @@ namespace currency static void init_options(boost::program_options::options_description& desc); bool init(const boost::program_options::variables_map& vm); + void set_rpc_chain_handler(epee::net_utils::http::i_chain_handler* prpc_chain_handler) { m_prpc_chain_handler = prpc_chain_handler; } bool on_get_blocks_direct(const COMMAND_RPC_GET_BLOCKS_DIRECT::request& req, COMMAND_RPC_GET_BLOCKS_DIRECT::response& res, connection_context& cntx); @@ -149,7 +150,9 @@ namespace currency MAP_JON_RPC ("get_current_core_tx_expiration_median", on_get_current_core_tx_expiration_median, COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN) // MAP_JON_RPC_WE("marketplace_global_get_offers_ex", on_get_offers_ex, COMMAND_RPC_GET_OFFERS_EX) + CHAIN_TO_PHANDLER(m_prpc_chain_handler) END_JSON_RPC_MAP() + CHAIN_TO_PHANDLER(m_prpc_chain_handler) END_URI_MAP2() private: @@ -170,6 +173,7 @@ namespace currency std::string m_port; std::string m_bind_ip; bool m_ignore_status; + epee::net_utils::http::i_chain_handler* m_prpc_chain_handler = nullptr; }; } diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index a5068051..98a3a5ab 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -59,13 +59,14 @@ namespace tools } //------------------------------------------------------------------------------------------------------------------------------ wallet_rpc_server::wallet_rpc_server(std::shared_ptr wptr): - m_pwallet_provider(new wallet_provider_simple(wptr)) + m_pwallet_provider_sh_ptr(new wallet_provider_simple(wptr)) + , m_pwallet_provider(m_pwallet_provider_sh_ptr.get()) , m_do_mint(false) , m_deaf(false) , m_last_wallet_store_height(0) {} //------------------------------------------------------------------------------------------------------------------------------ - wallet_rpc_server::wallet_rpc_server(std::shared_ptr provider_ptr): + wallet_rpc_server::wallet_rpc_server(i_wallet_provider* provider_ptr): m_pwallet_provider(provider_ptr) , m_do_mint(false) , m_deaf(false) diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index 653c592b..f0c4e178 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_rpc_server.h @@ -26,14 +26,15 @@ namespace tools struct wallet_rpc_locker { - wallet_rpc_locker(std::shared_ptr wallet_provider) :m_pwallet_provider(wallet_provider) + wallet_rpc_locker(i_wallet_provider* wallet_provider) :m_pwallet_provider(wallet_provider) { - m_wallet_ptr = get_wallet(); + m_pwallet_provider->lock(); + + m_wallet_ptr = m_pwallet_provider->get_wallet(); if (!m_wallet_ptr.get()) { throw std::runtime_error("Wallet object closed"); } - m_pwallet_provider->lock(); } std::shared_ptr get_wallet() { return m_wallet_ptr; } @@ -45,7 +46,7 @@ namespace tools private: std::shared_ptr m_wallet_ptr; - std::shared_ptr m_pwallet_provider; + i_wallet_provider* m_pwallet_provider; }; @@ -66,13 +67,13 @@ namespace tools /************************************************************************/ /* */ /************************************************************************/ - class wallet_rpc_server : public epee::http_server_impl_base + class wallet_rpc_server : public epee::http_server_impl_base, public epee::net_utils::http::i_chain_handler { public: typedef epee::net_utils::connection_context_base connection_context; wallet_rpc_server(std::shared_ptr wptr); - wallet_rpc_server(std::shared_ptr provider_ptr); + wallet_rpc_server(i_wallet_provider* provider_ptr); const static command_line::arg_descriptor arg_rpc_bind_port; const static command_line::arg_descriptor arg_rpc_bind_ip; @@ -85,7 +86,7 @@ namespace tools bool run(bool do_mint, bool offline_mode, const currency::account_public_address& miner_address); bool handle_http_request(const epee::net_utils::http::http_request_info& query_info, epee::net_utils::http::http_response_info& response, connection_context& m_conn_context); - BEGIN_URI_MAP2() + BEGIN_URI_MAP2_VIRTUAL() BEGIN_JSON_RPC_MAP("/json_rpc") MAP_JON_RPC_WE("getbalance", on_getbalance, wallet_public::COMMAND_RPC_GET_BALANCE) MAP_JON_RPC_WE("getaddress", on_getaddress, wallet_public::COMMAND_RPC_GET_ADDRESS) @@ -199,7 +200,8 @@ namespace tools bool handle_command_line(const boost::program_options::variables_map& vm); private: - std::shared_ptr m_pwallet_provider; + std::shared_ptr m_pwallet_provider_sh_ptr; + i_wallet_provider* m_pwallet_provider; std::string m_port; std::string m_bind_ip; bool m_do_mint; diff --git a/src/wallet/wallets_manager.cpp b/src/wallet/wallets_manager.cpp index d8159122..c98ef0a2 100644 --- a/src/wallet/wallets_manager.cpp +++ b/src/wallet/wallets_manager.cpp @@ -73,6 +73,7 @@ wallets_manager::wallets_manager():m_pview(&m_view_stub), m_rpc_server(m_ccore, m_p2psrv, m_offers_service), m_rpc_proxy(new tools::core_fast_rpc_proxy(m_rpc_server)), m_offers_service(nullptr), + m_wallet_rpc_server(this), #else m_rpc_proxy(new tools::default_http_core_proxy()), #endif @@ -545,6 +546,11 @@ bool wallets_manager::init_local_daemon() CHECK_AND_ASSERT_AND_SET_GUI(res, "Failed to initialize core rpc server."); LOG_PRINT_GREEN("Core rpc server initialized OK on port: " << m_rpc_server.get_binded_port(), LOG_LEVEL_0); + //chain calls to rpc server + m_prpc_chain_handler = &m_wallet_rpc_server; + m_rpc_server.set_rpc_chain_handler(this); + + LOG_PRINT_L0("Starting core rpc server..."); //dsi.text_state = "Starting core rpc server"; m_pview->update_daemon_status(dsi); @@ -2043,12 +2049,51 @@ bool wallets_manager::on_mw_select_wallet(uint64_t wallet_id) auto it = m_wallets.find(wallet_id); if (it == m_wallets.end()) return false; - auto& wo = it->second; - //m_wallet_rpc_server.reset_active_wallet(wo.w); + + m_rpc_selected_wallet_id = wallet_id; return false; } +bool wallets_manager::on_mw_get_wallets(const tools::wallet_public::COMMAND_MW_GET_WALLETS::request& req, tools::wallet_public::COMMAND_MW_GET_WALLETS::response& res, epee::json_rpc::error& er, epee::net_utils::connection_context_base& cntx) +{ + this->on_mw_get_wallets(res.wallets); + return true; +} +bool wallets_manager::on_mw_select_wallet(const tools::wallet_public::COMMAND_MW_SELECT_WALLET::request& req, tools::wallet_public::COMMAND_MW_SELECT_WALLET::response& res, epee::json_rpc::error& er, epee::net_utils::connection_context_base& cntx) +{ + this->on_mw_select_wallet(req.wallet_id); + return true; +} + + +void wallets_manager::lock() +{ + { + SHARED_CRITICAL_REGION_LOCAL(m_wallets_lock); + auto it = m_wallets.find(m_rpc_selected_wallet_id); + if (it == m_wallets.end()) + { + throw std::runtime_error("Wallet not selected"); + } + m_current_wallet_locked_object = it->second.w.lock(); + } +} + +void wallets_manager::unlock() +{ + m_current_wallet_locked_object.reset(); +} + +std::shared_ptr wallets_manager::get_wallet() +{ + if (!m_current_wallet_locked_object.get()) + { + throw std::runtime_error("Wallet is not locked for get_wallet() call"); + } + return **m_current_wallet_locked_object; +} + void wallets_manager::wallet_vs_options::worker_func() { LOG_PRINT_GREEN("[WALLET_HANDLER] Wallet handler thread started, addr: " << w->get()->get_account().get_public_address_str(), LOG_LEVEL_0); diff --git a/src/wallet/wallets_manager.h b/src/wallet/wallets_manager.h index b9542b2a..636e731c 100644 --- a/src/wallet/wallets_manager.h +++ b/src/wallet/wallets_manager.h @@ -47,7 +47,7 @@ struct wallet_lock_time_watching_policy }; -class wallets_manager : public i_backend_wallet_callback +class wallets_manager : public i_backend_wallet_callback, public tools::i_wallet_provider, epee::net_utils::http::i_chain_handler { public: @@ -55,6 +55,7 @@ public: { currency::core_runtime_config core_conf; epee::locked_object, wallet_lock_time_watching_policy> w; + typedef epee::locked_object, wallet_lock_time_watching_policy>::lock_shared_ptr wallet_lock_object; std::shared_ptr rpc_wrapper; //500 bytes of extra data, we can afford it, to have rpc-like invoke map std::atomic do_mining; std::atomic major_stop; @@ -196,8 +197,27 @@ private: virtual void on_mw_get_wallets(std::vector& wallets) override; virtual bool on_mw_select_wallet(uint64_t wallet_id) override; + //----- i_wallet_provider ------ + virtual void lock(); + virtual void unlock(); + virtual std::shared_ptr get_wallet(); //-------- + BEGIN_URI_MAP2_VIRTUAL() + BEGIN_JSON_RPC_MAP("/json_rpc") + //MULTIWALLET APIs + MAP_JON_RPC_WE("mw_get_wallets", on_mw_get_wallets, tools::wallet_public::COMMAND_MW_GET_WALLETS) + MAP_JON_RPC_WE("mw_select_wallet", on_mw_select_wallet, tools::wallet_public::COMMAND_MW_SELECT_WALLET) + CHAIN_TO_PHANDLER(m_prpc_chain_handler) + END_JSON_RPC_MAP() + CHAIN_TO_PHANDLER(m_prpc_chain_handler) + END_URI_MAP2() + + bool on_mw_get_wallets(const tools::wallet_public::COMMAND_MW_GET_WALLETS::request& req, tools::wallet_public::COMMAND_MW_GET_WALLETS::response& res, epee::json_rpc::error& er, epee::net_utils::connection_context_base& cntx); + bool on_mw_select_wallet(const tools::wallet_public::COMMAND_MW_SELECT_WALLET::request& req, tools::wallet_public::COMMAND_MW_SELECT_WALLET::response& res, epee::json_rpc::error& er, epee::net_utils::connection_context_base& cntx); + + + epee::net_utils::http::i_chain_handler* m_prpc_chain_handler = nullptr; std::thread m_main_worker_thread; std::atomic m_stop_singal_sent; @@ -228,6 +248,10 @@ private: currency::t_currency_protocol_handler m_cprotocol; nodetool::node_server > m_p2psrv; currency::core_rpc_server m_rpc_server; + + tools::wallet_rpc_server m_wallet_rpc_server; + wallet_vs_options::wallet_lock_object m_current_wallet_locked_object; + uint64_t m_rpc_selected_wallet_id = 0; #endif bool m_remote_node_mode;