diff --git a/contrib/epee/include/console_handler.h b/contrib/epee/include/console_handler.h index 55d021744..f2533eba0 100644 --- a/contrib/epee/include/console_handler.h +++ b/contrib/epee/include/console_handler.h @@ -350,7 +350,6 @@ namespace epee return true; }*/ - // TODO - Should this live somewhere else? class command_handler { public: typedef boost::function &)> callback; @@ -403,32 +402,13 @@ namespace epee /************************************************************************/ /* */ /************************************************************************/ - class console_handlers_binder + class console_handlers_binder : public command_handler { typedef command_handler::callback console_command_handler; typedef command_handler::lookup command_handlers_map; - command_handler m_command_handler; std::unique_ptr m_console_thread; async_console_handler m_console_handler; public: - std::string get_usage() - { - return m_command_handler.get_usage(); - } - void set_handler(const std::string& cmd, const console_command_handler& hndlr, const std::string& usage = "") - { - m_command_handler.set_handler(cmd, hndlr, usage); - } - bool process_command_vec(const std::vector& cmd) - { - return m_command_handler.process_command_vec(cmd); - } - - bool process_command_str(const std::string& cmd) - { - return m_command_handler.process_command_str(cmd); - } - bool start_handling(const std::string& prompt, const std::string& usage_string = "") { m_console_thread.reset(new boost::thread(boost::bind(&console_handlers_binder::run_handling, this, prompt, usage_string))); @@ -447,32 +427,31 @@ namespace epee } }; - /* work around because of broken boost bind */ - template - class srv_console_handlers_binder: public console_handlers_binder - { - bool process_command_str(t_server* /*psrv*/, const std::string& cmd) - { - return console_handlers_binder::process_command_str(cmd); - } - public: - bool start_handling(t_server* psrv, const std::string& prompt, const std::string& usage_string = "") - { - boost::thread(boost::bind(&srv_console_handlers_binder::run_handling, this, psrv, prompt, usage_string)).detach(); - return true; - } + ///* work around because of broken boost bind */ + //template + //class srv_console_handlers_binder: public command_handler + //{ + // async_console_handler m_console_handler; + //public: + // bool start_handling(t_server* psrv, const std::string& prompt, const std::string& usage_string = "") + // { + // boost::thread(boost::bind(&srv_console_handlers_binder::run_handling, this, psrv, prompt, usage_string)).detach(); + // return true; + // } - bool run_handling(t_server* psrv, const std::string& prompt, const std::string& usage_string) - { - return m_console_handler.run(psrv, boost::bind(&srv_console_handlers_binder::process_command_str, this, _1, _2), prompt, usage_string); - } + // bool run_handling(t_server* psrv, const std::string& prompt, const std::string& usage_string) + // { + // return m_console_handler.run(psrv, boost::bind(&srv_console_handlers_binder::process_command_str, this, _1, _2), prompt, usage_string); + // } - void stop_handling() - { - m_console_handler.stop(); - } - - private: - async_console_handler m_console_handler; - }; + // void stop_handling() + // { + // m_console_handler.stop(); + // } + //private: + // bool process_command_str(t_server* /*psrv*/, const std::string& cmd) + // { + // return console_handlers_binder::process_command_str(cmd); + // } + //}; } diff --git a/src/daemon/daemon_commands_handler.h b/src/daemon/command_server.h similarity index 60% rename from src/daemon/daemon_commands_handler.h rename to src/daemon/command_server.h index 5ead9691f..c333a6b73 100644 --- a/src/daemon/daemon_commands_handler.h +++ b/src/daemon/command_server.h @@ -1,108 +1,57 @@ -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - #pragma once -#include - #include "console_handler.h" -#include "p2p/net_node.h" #include "cryptonote_core/cryptonote_core.h" #include "cryptonote_protocol/cryptonote_protocol_handler.h" -#include "common/util.h" -#include "crypto/hash.h" -#include "version.h" +#include "p2p/net_node.h" +#include +namespace daemonize { -class daemon_cmmands_handler +namespace p = std::placeholders; +using namespace epee; + +class t_command_server_backend { - nodetool::node_server >& m_srv; public: - daemon_cmmands_handler(nodetool::node_server >& srv):m_srv(srv) - { - m_cmd_binder.set_handler("help", boost::bind(&daemon_cmmands_handler::help, this, _1), "Show this help"); - m_cmd_binder.set_handler("print_pl", boost::bind(&daemon_cmmands_handler::print_pl, this, _1), "Print peer list"); - m_cmd_binder.set_handler("print_cn", boost::bind(&daemon_cmmands_handler::print_cn, this, _1), "Print connections"); - m_cmd_binder.set_handler("print_bc", boost::bind(&daemon_cmmands_handler::print_bc, this, _1), "Print blockchain info in a given blocks range, print_bc []"); - //m_cmd_binder.set_handler("print_bci", boost::bind(&daemon_cmmands_handler::print_bci, this, _1)); - //m_cmd_binder.set_handler("print_bc_outs", boost::bind(&daemon_cmmands_handler::print_bc_outs, this, _1)); - m_cmd_binder.set_handler("print_block", boost::bind(&daemon_cmmands_handler::print_block, this, _1), "Print block, print_block | "); - m_cmd_binder.set_handler("print_tx", boost::bind(&daemon_cmmands_handler::print_tx, this, _1), "Print transaction, print_tx "); - m_cmd_binder.set_handler("start_mining", boost::bind(&daemon_cmmands_handler::start_mining, this, _1), "Start mining for specified address, start_mining [threads=1]"); - m_cmd_binder.set_handler("stop_mining", boost::bind(&daemon_cmmands_handler::stop_mining, this, _1), "Stop mining"); - m_cmd_binder.set_handler("print_pool", boost::bind(&daemon_cmmands_handler::print_pool, this, _1), "Print transaction pool (long format)"); - m_cmd_binder.set_handler("print_pool_sh", boost::bind(&daemon_cmmands_handler::print_pool_sh, this, _1), "Print transaction pool (short format)"); - m_cmd_binder.set_handler("show_hr", boost::bind(&daemon_cmmands_handler::show_hr, this, _1), "Start showing hash rate"); - m_cmd_binder.set_handler("hide_hr", boost::bind(&daemon_cmmands_handler::hide_hr, this, _1), "Stop showing hash rate"); - m_cmd_binder.set_handler("save", boost::bind(&daemon_cmmands_handler::save, this, _1), "Save blockchain"); - m_cmd_binder.set_handler("set_log", boost::bind(&daemon_cmmands_handler::set_log, this, _1), "set_log - Change current log detalization level, is a number 0-4"); - m_cmd_binder.set_handler("diff", boost::bind(&daemon_cmmands_handler::diff, this, _1), "Show difficulty"); - } - - bool start_handling() - { - m_cmd_binder.start_handling(&m_srv, "", ""); - return true; - } - - void stop_handling() - { - m_cmd_binder.stop_handling(); - } - + typedef nodetool::node_server > t_node_server; private: - epee::srv_console_handlers_binder > > m_cmd_binder; + t_node_server & m_srv; +public: + t_command_server_backend(t_node_server & srv) : + m_srv(srv) + {} - //-------------------------------------------------------------------------------- - std::string get_commands_str() - { - std::stringstream ss; - ss << CRYPTONOTE_NAME << " v" << PROJECT_VERSION_LONG << ENDL; - ss << "Commands: " << ENDL; - std::string usage = m_cmd_binder.get_usage(); - boost::replace_all(usage, "\n", "\n "); - usage.insert(0, " "); - ss << usage << ENDL; - return ss.str(); - } - //-------------------------------------------------------------------------------- - bool help(const std::vector& args) - { - std::cout << get_commands_str() << ENDL; - return true; - } - //-------------------------------------------------------------------------------- bool print_pl(const std::vector& args) { m_srv.log_peerlist(); return true; } - //-------------------------------------------------------------------------------- + bool save(const std::vector& args) { m_srv.get_payload_object().get_core().get_blockchain_storage().store_blockchain(); return true; } - //-------------------------------------------------------------------------------- + bool show_hr(const std::vector& args) { - if(!m_srv.get_payload_object().get_core().get_miner().is_mining()) - { - std::cout << "Mining is not started. You need start mining before you can see hash rate." << ENDL; - } else - { - m_srv.get_payload_object().get_core().get_miner().do_print_hashrate(true); - } + if(!m_srv.get_payload_object().get_core().get_miner().is_mining()) + { + std::cout << "Mining is not started. You need start mining before you can see hash rate." << ENDL; + } else + { + m_srv.get_payload_object().get_core().get_miner().do_print_hashrate(true); + } return true; } - //-------------------------------------------------------------------------------- + bool hide_hr(const std::vector& args) { m_srv.get_payload_object().get_core().get_miner().do_print_hashrate(false); return true; } - //-------------------------------------------------------------------------------- + bool diff(const std::vector& args) { cryptonote::difficulty_type difficulty = m_srv.get_payload_object().get_core().get_blockchain_storage().get_difficulty_for_next_block(); @@ -113,7 +62,7 @@ private: return true; } - //-------------------------------------------------------------------------------- + bool print_bc_outs(const std::vector& args) { if(args.size() != 1) @@ -124,13 +73,13 @@ private: m_srv.get_payload_object().get_core().print_blockchain_outs(args[0]); return true; } - //-------------------------------------------------------------------------------- + bool print_cn(const std::vector& args) { m_srv.get_payload_object().log_connections(); return true; } - //-------------------------------------------------------------------------------- + bool print_bc(const std::vector& args) { if(!args.size()) @@ -169,7 +118,7 @@ private: m_srv.get_payload_object().get_core().print_blockchain(start_index, end_index); return true; } - //-------------------------------------------------------------------------------- + bool print_bci(const std::vector& args) { m_srv.get_payload_object().get_core().print_blockchain_index(); @@ -202,14 +151,13 @@ private: return true; } - //-------------------------------------------------------------------------------- template static bool print_as_json(T& obj) { std::cout << cryptonote::obj_to_json_str(obj) << ENDL; return true; } - //-------------------------------------------------------------------------------- + bool print_block_by_height(uint64_t height) { std::list blocks; @@ -232,7 +180,7 @@ private: return true; } - //-------------------------------------------------------------------------------- + bool print_block_by_hash(const std::string& arg) { crypto::hash block_hash; @@ -260,7 +208,7 @@ private: return true; } - //-------------------------------------------------------------------------------- + bool print_block(const std::vector& args) { if (args.empty()) @@ -282,7 +230,7 @@ private: return true; } - //-------------------------------------------------------------------------------- + bool print_tx(const std::vector& args) { if (args.empty()) @@ -316,18 +264,19 @@ private: return true; } - //-------------------------------------------------------------------------------- + bool print_pool(const std::vector& args) { LOG_PRINT_L0("Pool state: " << ENDL << m_srv.get_payload_object().get_core().print_pool(false)); return true; } - //-------------------------------------------------------------------------------- + bool print_pool_sh(const std::vector& args) { LOG_PRINT_L0("Pool state: " << ENDL << m_srv.get_payload_object().get_core().print_pool(true)); return true; - } //-------------------------------------------------------------------------------- + } + bool start_mining(const std::vector& args) { if(!args.size()) @@ -355,10 +304,65 @@ private: m_srv.get_payload_object().get_core().get_miner().start(adr, threads_count, attrs); return true; } - //-------------------------------------------------------------------------------- + bool stop_mining(const std::vector& args) { m_srv.get_payload_object().get_core().get_miner().stop(); return true; } }; + +class t_command_server { +private: + t_command_server_backend m_backend; + command_handler m_handler; +public: + t_command_server(t_command_server_backend::t_node_server & server) : + m_backend(server) + , m_handler() + { + m_handler.set_handler("help", std::bind(&t_command_server::help, this, p::_1), "Show this help"); + m_handler.set_handler("print_pl", std::bind(&t_command_server_backend::print_pl, &m_backend, p::_1), "Print peer list"); + m_handler.set_handler("print_cn", std::bind(&t_command_server_backend::print_cn, &m_backend, p::_1), "Print connections"); + m_handler.set_handler("print_bc", std::bind(&t_command_server_backend::print_bc, &m_backend, p::_1), "Print blockchain info in a given blocks range, print_bc []"); + //m_handler.set_handler("print_bci", std::bind(&t_command_server_backend::print_bci, &m_backend, p::_1)); + //m_handler.set_handler("print_bc_outs", std::bind(&t_command_server_backend::print_bc_outs, &m_backend, p::_1)); + m_handler.set_handler("print_block", std::bind(&t_command_server_backend::print_block, &m_backend, p::_1), "Print block, print_block | "); + m_handler.set_handler("print_tx", std::bind(&t_command_server_backend::print_tx, &m_backend, p::_1), "Print transaction, print_tx "); + m_handler.set_handler("start_mining", std::bind(&t_command_server_backend::start_mining, &m_backend, p::_1), "Start mining for specified address, start_mining [threads=1]"); + m_handler.set_handler("stop_mining", std::bind(&t_command_server_backend::stop_mining, &m_backend, p::_1), "Stop mining"); + m_handler.set_handler("print_pool", std::bind(&t_command_server_backend::print_pool, &m_backend, p::_1), "Print transaction pool (long format)"); + m_handler.set_handler("print_pool_sh", std::bind(&t_command_server_backend::print_pool_sh, &m_backend, p::_1), "Print transaction pool (short format)"); + m_handler.set_handler("show_hr", std::bind(&t_command_server_backend::show_hr, &m_backend, p::_1), "Start showing hash rate"); + m_handler.set_handler("hide_hr", std::bind(&t_command_server_backend::hide_hr, &m_backend, p::_1), "Stop showing hash rate"); + m_handler.set_handler("save", std::bind(&t_command_server_backend::save, &m_backend, p::_1), "Save blockchain"); + m_handler.set_handler("set_log", std::bind(&t_command_server_backend::set_log, &m_backend, p::_1), "set_log - Change current log detalization level, is a number 0-4"); + m_handler.set_handler("diff", std::bind(&t_command_server_backend::diff, &m_backend, p::_1), "Show difficulty"); + } + + bool process_command(const std::string& cmd) + { + return m_handler.process_command_str(cmd); + } + +private: + bool help(const std::vector& args) + { + std::cout << get_commands_str() << ENDL; + return true; + } + + std::string get_commands_str() + { + std::stringstream ss; + ss << CRYPTONOTE_NAME << " v" << PROJECT_VERSION_LONG << ENDL; + ss << "Commands: " << ENDL; + std::string usage = m_handler.get_usage(); + boost::replace_all(usage, "\n", "\n "); + usage.insert(0, " "); + ss << usage << ENDL; + return ss.str(); + } +}; + +} // namespace daemonize diff --git a/src/daemon/console_command_thread.h b/src/daemon/console_command_thread.h new file mode 100644 index 000000000..67a374d06 --- /dev/null +++ b/src/daemon/console_command_thread.h @@ -0,0 +1,51 @@ +// Copyright (c) 2012-2013 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#pragma once + +#include "console_handler.h" +#include "cryptonote_core/cryptonote_core.h" +#include "cryptonote_protocol/cryptonote_protocol_handler.h" +#include "daemon/command_server.h" +#include "p2p/net_node.h" +#include + +namespace daemonize { + +class t_console_command_thread +{ +public: + typedef nodetool::node_server > t_server; +private: + t_command_server m_server; + t_server & m_srv; + async_console_handler m_console_handler; +public: + t_console_command_thread(nodetool::node_server >& srv) : + m_server(srv) + , m_srv(srv) + , m_console_handler() + {} + + void start() + { + using namespace std::placeholders; + + auto process_command_callback = [this](t_server* /*psrv*/, const std::string& cmd) { + return m_server.process_command(cmd); + }; + + auto loop = [this, process_command_callback]() { + m_console_handler.run(&m_srv, process_command_callback, "", ""); + }; + std::thread(loop).detach(); + } + + void stop() + { + m_console_handler.stop(); + } +}; + +} // namespace daemonize diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index 24906de1b..c15a8650b 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -8,6 +8,7 @@ #include "include_base_utils.h" #include "version.h" +#include "daemon/console_command_thread.h" using namespace epee; @@ -21,13 +22,17 @@ using namespace epee; #include "cryptonote_core/cryptonote_core.h" #include "rpc/core_rpc_server.h" #include "cryptonote_protocol/cryptonote_protocol_handler.h" -#include "daemon_commands_handler.h" -#include "version.h" + +//#if !defined(WIN32) +//#include "posix_daemonize.h" +//#endif #if defined(WIN32) #include #endif +using namespace daemonize; + namespace po = boost::program_options; namespace bf = boost::filesystem; @@ -43,14 +48,14 @@ namespace const command_line::arg_descriptor arg_stop_daemon = {"stop", "Stop running daemon"}; const command_line::arg_descriptor arg_help_daemon = {"daemon-help", "Display daemon command help"}; const command_line::arg_descriptor arg_daemon_command = {"send-command", "Send a command string to the running daemon"}; -} -bool is_there_more_than_one(po::variables_map vm, std::initializer_list arg_names) { - int count = 0; - for (auto & arg_name : arg_names) { - if (vm[arg_name].empty() || !vm[arg_name].defaulted()) ++count; + bool is_there_more_than_one(po::variables_map vm, std::initializer_list arg_names) { + int count = 0; + for (auto & arg_name : arg_names) { + if (vm[arg_name].empty() || !vm[arg_name].defaulted()) ++count; + } + return count > 1; } - return count > 1; } int main(int argc, char* argv[]) @@ -226,7 +231,7 @@ int main(int argc, char* argv[]) cryptonote::core_rpc_server rpc_server(ccore, p2psrv); cprotocol.set_p2p_endpoint(&p2psrv); ccore.set_cryptonote_protocol(&cprotocol); - daemon_cmmands_handler dch(p2psrv); + t_console_command_thread console_command_thread(p2psrv); //initialize objects LOG_PRINT_L0("Initializing p2p server..."); @@ -253,7 +258,7 @@ int main(int argc, char* argv[]) // start components if(!command_line::has_arg(vm, arg_console)) { - dch.start_handling(); + console_command_thread.start(); } LOG_PRINT_L0("Starting core rpc server..."); @@ -261,8 +266,8 @@ int main(int argc, char* argv[]) CHECK_AND_ASSERT_MES(res, 1, "Failed to initialize core rpc server."); LOG_PRINT_L0("Core rpc server started ok"); - tools::signal_handler::install([&dch, &p2psrv] { - dch.stop_handling(); + tools::signal_handler::install([&console_command_thread, &p2psrv] { + console_command_thread.stop(); p2psrv.send_stop_signal(); });