diff --git a/src/console_commands.cpp b/src/console_commands.cpp index 8417ab9..431e612 100644 --- a/src/console_commands.cpp +++ b/src/console_commands.cpp @@ -1,6 +1,7 @@ /* * This file is part of the Monero P2Pool * Copyright (c) 2021 SChernykh + * Copyright (c) 2021 hyc * * 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 @@ -51,6 +52,89 @@ ConsoleCommands::~ConsoleCommands() LOGINFO(1, "stopped"); } +typedef struct strconst { + const char *str; + size_t len; +} strconst; + +#define STRCONST(x) {x, sizeof(x)-1} +#define STRCNULL {NULL, 0} + +typedef int (cmdfunc)(p2pool *pool, const char *args); + +typedef struct cmd { + strconst name; + const char *arg; + const char *descr; + cmdfunc *func; +} cmd; + +static cmdfunc do_help, do_status, do_loglevel, do_addpeers, do_droppeers, do_exit; + +static cmd cmds[] = { + { STRCONST("help"), "", "display list of commands", do_help }, + { STRCONST("status"), "", "display p2pool status", do_status }, + { STRCONST("loglevel"), "", "set log level", do_loglevel }, + { STRCONST("addpeers"), "", "add peer", do_addpeers }, + { STRCONST("droppeers"), "", "disconnect all peers", do_droppeers }, + { STRCONST("exit"), "", "terminate p2pool", do_exit }, + { STRCNULL, NULL, NULL, NULL } +}; + +static int do_help(p2pool * /* m_pool */, const char * /* args */) +{ + int i; + + LOGINFO(0, "List of commands"); + for (i=0; cmds[i].name.len; i++) + LOGINFO(0, cmds[i].name.str << " " << cmds[i].arg << "\t" << cmds[i].descr); + return 0; +} + +static int do_status(p2pool *m_pool, const char * /* args */) +{ + m_pool->side_chain().print_status(); + if (m_pool->stratum_server()) { + m_pool->stratum_server()->print_status(); + } + if (m_pool->p2p_server()) { + m_pool->p2p_server()->print_status(); + } + return 0; +} + +static int do_loglevel(p2pool * /* m_pool */, const char *args) +{ + int level = atoi(args); + level = std::min(std::max(level, 0), 5); + log::GLOBAL_LOG_LEVEL = level; + LOGINFO(0, "log level set to " << level); + return 0; +} + +static int do_addpeers(p2pool *m_pool, const char *args) +{ + if (m_pool->p2p_server()) { + m_pool->p2p_server()->connect_to_peers(args); + } + return 0; +} + +static int do_droppeers(p2pool *m_pool, const char * /* args */) +{ + if (m_pool->p2p_server()) { + m_pool->p2p_server()->drop_connections(); + } + return 0; +} + +static int do_exit(p2pool *m_pool, const char * /* args */) +{ + m_pool->stop(); + + return 1; +} + void ConsoleCommands::run() { LOGINFO(1, "started"); @@ -58,51 +142,24 @@ void ConsoleCommands::run() std::string command; command.reserve(1024); - constexpr char status[] = "status"; - constexpr char loglevel[] = "loglevel"; - constexpr char addpeers[] = "addpeers"; - constexpr char droppeers[] = "droppeers"; - do { std::getline(std::cin, command); if (stopped || std::cin.eof()) { return; } - if (command.find(status) == 0) { - m_pool->side_chain().print_status(); - if (m_pool->stratum_server()) { - m_pool->stratum_server()->print_status(); - } - if (m_pool->p2p_server()) { - m_pool->p2p_server()->print_status(); - } - continue; - } - - if (command.find(loglevel) == 0) { - int level = atoi(command.c_str() + sizeof(loglevel)); - level = std::min(std::max(level, 0), 5); - log::GLOBAL_LOG_LEVEL = level; - LOGINFO(0, "log level set to " << level); - continue; - } - - if (command.find(addpeers) == 0) { - if (m_pool->p2p_server()) { - m_pool->p2p_server()->connect_to_peers(command.c_str() + sizeof(addpeers)); + int i; + for (i=0; cmds[i].name.len; i++) { + if (!strncmp(command.c_str(), cmds[i].name.str, cmds[i].name.len)) { + const char *args = command.c_str() + cmds[i].name.len + 1; + int rc = cmds[i].func(m_pool, args); + if ( rc ) + return; + break; } - continue; } - - if (command.find(droppeers) == 0) { - if (m_pool->p2p_server()) { - m_pool->p2p_server()->drop_connections(); - } - continue; - } - - LOGWARN(0, "Unknown command " << command); + if (!cmds[i].name.len) + LOGWARN(0, "Unknown command " << command); } while (true); } diff --git a/src/p2pool.cpp b/src/p2pool.cpp index 4e40a89..0e7978e 100644 --- a/src/p2pool.cpp +++ b/src/p2pool.cpp @@ -659,6 +659,17 @@ static bool init_signals() return true; } +void p2pool::stop() +{ + uv_async_t asy; + uv_loop_t *loop = uv_default_loop(); + + /* use async handle to make sure event loops wake up and stop */ + uv_async_init(loop, &asy, NULL); + uv_stop(loop); + uv_async_send(&asy); +} + int p2pool::run() { if (!m_params->ok()) { diff --git a/src/p2pool.h b/src/p2pool.h index d9349ba..27cc2a9 100644 --- a/src/p2pool.h +++ b/src/p2pool.h @@ -41,6 +41,7 @@ public: int run(); bool stopped() const { return m_stopped; } + void stop(); const Params& params() const { return *m_params; } BlockTemplate& block_template() { return *m_blockTemplate; } diff --git a/src/tcp_server.inl b/src/tcp_server.inl index 3598f81..7b06f44 100644 --- a/src/tcp_server.inl +++ b/src/tcp_server.inl @@ -393,6 +393,11 @@ void TCPServer::shutdown_tcp() uv_close(reinterpret_cast(s), [](uv_handle_t* h) { delete reinterpret_cast(h); }); } + uv_async_t asy; + uv_async_init(&m_loop, &asy, NULL); + uv_stop(&m_loop); + uv_async_send(&asy); + uv_thread_join(&m_loopThread); uv_loop_close(&m_loop);