oxen-core/contrib/epee/include/epee/console_handler.h

612 lines
17 KiB
C
Raw Normal View History

// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
2014-03-03 23:07:58 +01:00
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
2014-03-03 23:07:58 +01:00
#pragma once
#include "misc_log_ex.h"
#include "string_tools.h"
daemon & daemonize overhaul This commit continues the complete replacement of the spaghetti code mess that was inside daemon/ and daemonize/ which started in #1138, and looked like a entry level Java programmer threw up inside the code base. This greatly simplifies it, removing a whole pile of useless abstraction layers that don't actually abstract anything, and results in considerably simpler code. (Many of the changes here were also carried out in #1138; this commit updates them with the merged result which amends some things from that PR and goes further in some places). In detail: - the `--detach` (and related `--pidfile`) options are gone. (--detach is still handled, but now just prints a fatal error). Detaching a process is an archaic unix mechanism that has no place on a modern system. If you *really* want to do it anyway, `nohup lokid &` will do the job. (The Windows service control code, which is probably seldom used, is kept because it seems potentially useful for Windows users). - Many of the `t_whatever` classes in daemon/* are just deleted (mostly done in #1138); each one was a bunch of junk code that wraps 3-4 lines but forces an extra layer (not even a generic abstraction, just a useless wrapper) for no good reason and made the daemon code painfully hard to understand and work with. - All of the remaining `t_whatever` classes in daemon/* are either renamed to `whatever` (because prefixing every class with `t_` is moronic). - Some stupid related code (e.g. epee's command handler returning an unsuitable "usage" string that has to be string modified into what we want) was replaced with more generic, useful code. - Replaced boost mutexes/cvs with std ones in epee command handler, and deleted some commented out code. - The `--public-node` option handling was terrible: it was being handled in main, but main doesn't know anything about options, so then it forced it through the spaghetti objects *beside* the pack of all options that got passed along. Moved it to a more sane location (core_rpc_server) and parse it out with some sanity. - Changed a bunch of std::bind's to lambdas because, at least for small lambdas (i.e. with only one-or-two pointers for captures) they will generally be more efficient as the values can be stored in std::function's without any memory allocations.
2020-04-02 22:38:52 +02:00
#include <functional>
2014-03-20 12:46:11 +01:00
#include <atomic>
#include <condition_variable>
#include <functional>
#include <mutex>
#include <thread>
#include <iostream>
#include <any>
#include <unordered_map>
#include <optional>
2016-01-21 19:18:26 +01:00
#ifdef __OpenBSD__
#include <stdio.h>
#endif
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
2014-03-20 12:46:11 +01:00
#ifdef HAVE_READLINE
#include "readline_buffer.h"
#endif
#include "readline_suspend.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "console_handler"
2014-03-03 23:07:58 +01:00
namespace epee
{
2014-03-20 12:46:11 +01:00
class async_stdin_reader
{
public:
async_stdin_reader()
: m_run(true)
, m_has_read_request(false)
, m_read_status(state_init)
{
#ifdef HAVE_READLINE
m_readline_buffer.start();
#endif
daemon & daemonize overhaul This commit continues the complete replacement of the spaghetti code mess that was inside daemon/ and daemonize/ which started in #1138, and looked like a entry level Java programmer threw up inside the code base. This greatly simplifies it, removing a whole pile of useless abstraction layers that don't actually abstract anything, and results in considerably simpler code. (Many of the changes here were also carried out in #1138; this commit updates them with the merged result which amends some things from that PR and goes further in some places). In detail: - the `--detach` (and related `--pidfile`) options are gone. (--detach is still handled, but now just prints a fatal error). Detaching a process is an archaic unix mechanism that has no place on a modern system. If you *really* want to do it anyway, `nohup lokid &` will do the job. (The Windows service control code, which is probably seldom used, is kept because it seems potentially useful for Windows users). - Many of the `t_whatever` classes in daemon/* are just deleted (mostly done in #1138); each one was a bunch of junk code that wraps 3-4 lines but forces an extra layer (not even a generic abstraction, just a useless wrapper) for no good reason and made the daemon code painfully hard to understand and work with. - All of the remaining `t_whatever` classes in daemon/* are either renamed to `whatever` (because prefixing every class with `t_` is moronic). - Some stupid related code (e.g. epee's command handler returning an unsuitable "usage" string that has to be string modified into what we want) was replaced with more generic, useful code. - Replaced boost mutexes/cvs with std ones in epee command handler, and deleted some commented out code. - The `--public-node` option handling was terrible: it was being handled in main, but main doesn't know anything about options, so then it forced it through the spaghetti objects *beside* the pack of all options that got passed along. Moved it to a more sane location (core_rpc_server) and parse it out with some sanity. - Changed a bunch of std::bind's to lambdas because, at least for small lambdas (i.e. with only one-or-two pointers for captures) they will generally be more efficient as the values can be stored in std::function's without any memory allocations.
2020-04-02 22:38:52 +02:00
m_reader_thread = std::thread([this] { reader_thread_func(); });
2014-03-20 12:46:11 +01:00
}
2014-03-03 23:07:58 +01:00
2014-03-20 12:46:11 +01:00
~async_stdin_reader()
{
Merge pull request #4459 bcf3f6af fuzz_tests: catch unhandled exceptions (moneromooo-monero) 3ebd05d4 miner: restore stream flags after changing them (moneromooo-monero) a093092e levin_protocol_handler_async: do not propagate exception through dtor (moneromooo-monero) 1eebb82b net_helper: do not propagate exceptions through dtor (moneromooo-monero) fb6a3630 miner: do not propagate exceptions through dtor (moneromooo-monero) 2e2139ff epee: do not propagate exception through dtor (moneromooo-monero) 0749a8bd db_lmdb: do not propagate exceptions in dtor (moneromooo-monero) 1b0afeeb wallet_rpc_server: exit cleanly on unhandled exceptions (moneromooo-monero) 418a9936 unit_tests: catch unhandled exceptions (moneromooo-monero) ea7f9543 threadpool: do not propagate exceptions through the dtor (moneromooo-monero) 6e855422 gen_multisig: nice exit on unhandled exception (moneromooo-monero) 53df2deb db_lmdb: catch error in mdb_stat calls during migration (moneromooo-monero) e67016dd blockchain_blackball: catch failure to commit db transaction (moneromooo-monero) 661439f4 mlog: don't remove old logs if we failed to rename the current file (moneromooo-monero) 5fdcda50 easylogging++: test for NULL before dereference (moneromooo-monero) 7ece1550 performance_test: fix bad last argument calling add_arg (moneromooo-monero) a085da32 unit_tests: add check for page size > 0 before dividing (moneromooo-monero) d8b1ec8b unit_tests: use std::shared_ptr to shut coverity up about leaks (moneromooo-monero) 02563bf4 simplewallet: top level exception catcher to print nicer messages (moneromooo-monero) c57a65b2 blockchain_blackball: fix shift range for 32 bit archs (moneromooo-monero)
2018-09-29 22:17:00 +02:00
try { stop(); }
catch (...) { /* ignore */ }
2014-03-20 12:46:11 +01:00
}
2014-03-03 23:07:58 +01:00
#ifdef HAVE_READLINE
rdln::readline_buffer& get_readline_buffer()
{
return m_readline_buffer;
}
#endif
2014-03-20 12:46:11 +01:00
// Not thread safe. Only one thread can call this method at once.
bool get_line(std::string& line)
{
if (!start_read())
return false;
2014-03-03 23:07:58 +01:00
if (state_eos == m_read_status)
return false;
daemon & daemonize overhaul This commit continues the complete replacement of the spaghetti code mess that was inside daemon/ and daemonize/ which started in #1138, and looked like a entry level Java programmer threw up inside the code base. This greatly simplifies it, removing a whole pile of useless abstraction layers that don't actually abstract anything, and results in considerably simpler code. (Many of the changes here were also carried out in #1138; this commit updates them with the merged result which amends some things from that PR and goes further in some places). In detail: - the `--detach` (and related `--pidfile`) options are gone. (--detach is still handled, but now just prints a fatal error). Detaching a process is an archaic unix mechanism that has no place on a modern system. If you *really* want to do it anyway, `nohup lokid &` will do the job. (The Windows service control code, which is probably seldom used, is kept because it seems potentially useful for Windows users). - Many of the `t_whatever` classes in daemon/* are just deleted (mostly done in #1138); each one was a bunch of junk code that wraps 3-4 lines but forces an extra layer (not even a generic abstraction, just a useless wrapper) for no good reason and made the daemon code painfully hard to understand and work with. - All of the remaining `t_whatever` classes in daemon/* are either renamed to `whatever` (because prefixing every class with `t_` is moronic). - Some stupid related code (e.g. epee's command handler returning an unsuitable "usage" string that has to be string modified into what we want) was replaced with more generic, useful code. - Replaced boost mutexes/cvs with std ones in epee command handler, and deleted some commented out code. - The `--public-node` option handling was terrible: it was being handled in main, but main doesn't know anything about options, so then it forced it through the spaghetti objects *beside* the pack of all options that got passed along. Moved it to a more sane location (core_rpc_server) and parse it out with some sanity. - Changed a bunch of std::bind's to lambdas because, at least for small lambdas (i.e. with only one-or-two pointers for captures) they will generally be more efficient as the values can be stored in std::function's without any memory allocations.
2020-04-02 22:38:52 +02:00
std::unique_lock<std::mutex> lock(m_response_mutex);
m_response_cv.wait(lock, [this] { return m_read_status != state_init; });
2014-03-03 23:07:58 +01:00
2014-03-20 12:46:11 +01:00
bool res = false;
if (state_success == m_read_status)
{
line = m_line;
res = true;
}
2014-03-03 23:07:58 +01:00
if (!eos() && m_read_status != state_cancelled)
m_read_status = state_init;
2014-03-20 12:46:11 +01:00
return res;
}
bool eos() const { return m_read_status == state_eos; }
2014-03-20 12:46:11 +01:00
void stop()
{
if (m_run)
{
m_run.store(false, std::memory_order_relaxed);
#if defined(WIN32)
::CloseHandle(::GetStdHandle(STD_INPUT_HANDLE));
#endif
m_request_cv.notify_one();
m_reader_thread.join();
#ifdef HAVE_READLINE
m_readline_buffer.stop();
#endif
2014-03-20 12:46:11 +01:00
}
}
void cancel()
{
std::unique_lock<std::mutex> lock(m_response_mutex);
m_read_status = state_cancelled;
m_has_read_request = false;
m_response_cv.notify_one();
}
2014-03-20 12:46:11 +01:00
private:
bool start_read()
{
daemon & daemonize overhaul This commit continues the complete replacement of the spaghetti code mess that was inside daemon/ and daemonize/ which started in #1138, and looked like a entry level Java programmer threw up inside the code base. This greatly simplifies it, removing a whole pile of useless abstraction layers that don't actually abstract anything, and results in considerably simpler code. (Many of the changes here were also carried out in #1138; this commit updates them with the merged result which amends some things from that PR and goes further in some places). In detail: - the `--detach` (and related `--pidfile`) options are gone. (--detach is still handled, but now just prints a fatal error). Detaching a process is an archaic unix mechanism that has no place on a modern system. If you *really* want to do it anyway, `nohup lokid &` will do the job. (The Windows service control code, which is probably seldom used, is kept because it seems potentially useful for Windows users). - Many of the `t_whatever` classes in daemon/* are just deleted (mostly done in #1138); each one was a bunch of junk code that wraps 3-4 lines but forces an extra layer (not even a generic abstraction, just a useless wrapper) for no good reason and made the daemon code painfully hard to understand and work with. - All of the remaining `t_whatever` classes in daemon/* are either renamed to `whatever` (because prefixing every class with `t_` is moronic). - Some stupid related code (e.g. epee's command handler returning an unsuitable "usage" string that has to be string modified into what we want) was replaced with more generic, useful code. - Replaced boost mutexes/cvs with std ones in epee command handler, and deleted some commented out code. - The `--public-node` option handling was terrible: it was being handled in main, but main doesn't know anything about options, so then it forced it through the spaghetti objects *beside* the pack of all options that got passed along. Moved it to a more sane location (core_rpc_server) and parse it out with some sanity. - Changed a bunch of std::bind's to lambdas because, at least for small lambdas (i.e. with only one-or-two pointers for captures) they will generally be more efficient as the values can be stored in std::function's without any memory allocations.
2020-04-02 22:38:52 +02:00
std::unique_lock<std::mutex> lock(m_request_mutex);
2014-03-20 12:46:11 +01:00
if (!m_run.load(std::memory_order_relaxed) || m_has_read_request)
return false;
m_has_read_request = true;
m_request_cv.notify_one();
return true;
}
bool wait_read()
2014-03-03 23:07:58 +01:00
{
daemon & daemonize overhaul This commit continues the complete replacement of the spaghetti code mess that was inside daemon/ and daemonize/ which started in #1138, and looked like a entry level Java programmer threw up inside the code base. This greatly simplifies it, removing a whole pile of useless abstraction layers that don't actually abstract anything, and results in considerably simpler code. (Many of the changes here were also carried out in #1138; this commit updates them with the merged result which amends some things from that PR and goes further in some places). In detail: - the `--detach` (and related `--pidfile`) options are gone. (--detach is still handled, but now just prints a fatal error). Detaching a process is an archaic unix mechanism that has no place on a modern system. If you *really* want to do it anyway, `nohup lokid &` will do the job. (The Windows service control code, which is probably seldom used, is kept because it seems potentially useful for Windows users). - Many of the `t_whatever` classes in daemon/* are just deleted (mostly done in #1138); each one was a bunch of junk code that wraps 3-4 lines but forces an extra layer (not even a generic abstraction, just a useless wrapper) for no good reason and made the daemon code painfully hard to understand and work with. - All of the remaining `t_whatever` classes in daemon/* are either renamed to `whatever` (because prefixing every class with `t_` is moronic). - Some stupid related code (e.g. epee's command handler returning an unsuitable "usage" string that has to be string modified into what we want) was replaced with more generic, useful code. - Replaced boost mutexes/cvs with std ones in epee command handler, and deleted some commented out code. - The `--public-node` option handling was terrible: it was being handled in main, but main doesn't know anything about options, so then it forced it through the spaghetti objects *beside* the pack of all options that got passed along. Moved it to a more sane location (core_rpc_server) and parse it out with some sanity. - Changed a bunch of std::bind's to lambdas because, at least for small lambdas (i.e. with only one-or-two pointers for captures) they will generally be more efficient as the values can be stored in std::function's without any memory allocations.
2020-04-02 22:38:52 +02:00
std::unique_lock<std::mutex> lock(m_request_mutex);
m_request_cv.wait(lock, [this] { return m_has_read_request || !m_run; });
2014-03-03 23:07:58 +01:00
2014-03-20 12:46:11 +01:00
if (m_has_read_request)
2014-03-03 23:07:58 +01:00
{
2014-03-20 12:46:11 +01:00
m_has_read_request = false;
return true;
}
return false;
}
bool wait_stdin_data()
{
#if !defined(WIN32)
2017-01-05 02:11:05 +01:00
#if defined(__OpenBSD__) || defined(__ANDROID__)
2016-01-21 19:18:26 +01:00
int stdin_fileno = fileno(stdin);
#else
2014-03-20 12:46:11 +01:00
int stdin_fileno = ::fileno(stdin);
2016-01-21 19:18:26 +01:00
#endif
2014-03-20 12:46:11 +01:00
while (m_run.load(std::memory_order_relaxed))
2014-03-03 23:07:58 +01:00
{
if (m_read_status == state_cancelled)
return false;
2014-03-20 12:46:11 +01:00
fd_set read_set;
FD_ZERO(&read_set);
FD_SET(stdin_fileno, &read_set);
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 100 * 1000;
int retval = ::select(stdin_fileno + 1, &read_set, NULL, NULL, &tv);
if (retval < 0)
return false;
else if (0 < retval)
return true;
}
#else
while (m_run.load(std::memory_order_relaxed))
{
if (m_read_status == state_cancelled)
return false;
int retval = ::WaitForSingleObject(::GetStdHandle(STD_INPUT_HANDLE), 100);
switch (retval)
{
case WAIT_FAILED:
return false;
case WAIT_OBJECT_0:
return true;
default:
break;
}
}
2014-03-20 12:46:11 +01:00
#endif
return true;
}
void reader_thread_func()
{
while (true)
{
if (!wait_read())
break;
std::string line;
bool read_ok = true;
#ifdef HAVE_READLINE
reread:
#endif
2014-03-20 12:46:11 +01:00
if (wait_stdin_data())
2014-03-03 23:07:58 +01:00
{
2014-03-20 12:46:11 +01:00
if (m_run.load(std::memory_order_relaxed))
{
#ifdef HAVE_READLINE
switch (m_readline_buffer.get_line(line))
{
case rdln::empty: goto eof;
case rdln::partial: goto reread;
case rdln::full: break;
}
#else
if (m_read_status != state_cancelled)
std::getline(std::cin, line);
#endif
2014-03-20 12:46:11 +01:00
read_ok = !std::cin.eof() && !std::cin.fail();
}
2014-03-03 23:07:58 +01:00
}
2014-03-20 12:46:11 +01:00
else
2014-03-03 23:07:58 +01:00
{
2014-03-20 12:46:11 +01:00
read_ok = false;
}
if (std::cin.eof()) {
#ifdef HAVE_READLINE
eof:
#endif
m_read_status = state_eos;
m_response_cv.notify_one();
break;
}
else
2014-03-20 12:46:11 +01:00
{
daemon & daemonize overhaul This commit continues the complete replacement of the spaghetti code mess that was inside daemon/ and daemonize/ which started in #1138, and looked like a entry level Java programmer threw up inside the code base. This greatly simplifies it, removing a whole pile of useless abstraction layers that don't actually abstract anything, and results in considerably simpler code. (Many of the changes here were also carried out in #1138; this commit updates them with the merged result which amends some things from that PR and goes further in some places). In detail: - the `--detach` (and related `--pidfile`) options are gone. (--detach is still handled, but now just prints a fatal error). Detaching a process is an archaic unix mechanism that has no place on a modern system. If you *really* want to do it anyway, `nohup lokid &` will do the job. (The Windows service control code, which is probably seldom used, is kept because it seems potentially useful for Windows users). - Many of the `t_whatever` classes in daemon/* are just deleted (mostly done in #1138); each one was a bunch of junk code that wraps 3-4 lines but forces an extra layer (not even a generic abstraction, just a useless wrapper) for no good reason and made the daemon code painfully hard to understand and work with. - All of the remaining `t_whatever` classes in daemon/* are either renamed to `whatever` (because prefixing every class with `t_` is moronic). - Some stupid related code (e.g. epee's command handler returning an unsuitable "usage" string that has to be string modified into what we want) was replaced with more generic, useful code. - Replaced boost mutexes/cvs with std ones in epee command handler, and deleted some commented out code. - The `--public-node` option handling was terrible: it was being handled in main, but main doesn't know anything about options, so then it forced it through the spaghetti objects *beside* the pack of all options that got passed along. Moved it to a more sane location (core_rpc_server) and parse it out with some sanity. - Changed a bunch of std::bind's to lambdas because, at least for small lambdas (i.e. with only one-or-two pointers for captures) they will generally be more efficient as the values can be stored in std::function's without any memory allocations.
2020-04-02 22:38:52 +02:00
std::unique_lock<std::mutex> lock(m_response_mutex);
2014-03-20 12:46:11 +01:00
if (m_run.load(std::memory_order_relaxed))
{
m_line = std::move(line);
m_read_status = read_ok ? state_success : state_error;
}
else
{
m_read_status = state_cancelled;
}
m_response_cv.notify_one();
2014-03-03 23:07:58 +01:00
}
}
}
2014-03-20 12:46:11 +01:00
enum t_state
{
state_init,
state_success,
state_error,
state_cancelled,
state_eos
2014-03-20 12:46:11 +01:00
};
private:
daemon & daemonize overhaul This commit continues the complete replacement of the spaghetti code mess that was inside daemon/ and daemonize/ which started in #1138, and looked like a entry level Java programmer threw up inside the code base. This greatly simplifies it, removing a whole pile of useless abstraction layers that don't actually abstract anything, and results in considerably simpler code. (Many of the changes here were also carried out in #1138; this commit updates them with the merged result which amends some things from that PR and goes further in some places). In detail: - the `--detach` (and related `--pidfile`) options are gone. (--detach is still handled, but now just prints a fatal error). Detaching a process is an archaic unix mechanism that has no place on a modern system. If you *really* want to do it anyway, `nohup lokid &` will do the job. (The Windows service control code, which is probably seldom used, is kept because it seems potentially useful for Windows users). - Many of the `t_whatever` classes in daemon/* are just deleted (mostly done in #1138); each one was a bunch of junk code that wraps 3-4 lines but forces an extra layer (not even a generic abstraction, just a useless wrapper) for no good reason and made the daemon code painfully hard to understand and work with. - All of the remaining `t_whatever` classes in daemon/* are either renamed to `whatever` (because prefixing every class with `t_` is moronic). - Some stupid related code (e.g. epee's command handler returning an unsuitable "usage" string that has to be string modified into what we want) was replaced with more generic, useful code. - Replaced boost mutexes/cvs with std ones in epee command handler, and deleted some commented out code. - The `--public-node` option handling was terrible: it was being handled in main, but main doesn't know anything about options, so then it forced it through the spaghetti objects *beside* the pack of all options that got passed along. Moved it to a more sane location (core_rpc_server) and parse it out with some sanity. - Changed a bunch of std::bind's to lambdas because, at least for small lambdas (i.e. with only one-or-two pointers for captures) they will generally be more efficient as the values can be stored in std::function's without any memory allocations.
2020-04-02 22:38:52 +02:00
std::thread m_reader_thread;
2014-03-20 12:46:11 +01:00
std::atomic<bool> m_run;
#ifdef HAVE_READLINE
rdln::readline_buffer m_readline_buffer;
#endif
2014-03-20 12:46:11 +01:00
std::string m_line;
bool m_has_read_request;
t_state m_read_status;
daemon & daemonize overhaul This commit continues the complete replacement of the spaghetti code mess that was inside daemon/ and daemonize/ which started in #1138, and looked like a entry level Java programmer threw up inside the code base. This greatly simplifies it, removing a whole pile of useless abstraction layers that don't actually abstract anything, and results in considerably simpler code. (Many of the changes here were also carried out in #1138; this commit updates them with the merged result which amends some things from that PR and goes further in some places). In detail: - the `--detach` (and related `--pidfile`) options are gone. (--detach is still handled, but now just prints a fatal error). Detaching a process is an archaic unix mechanism that has no place on a modern system. If you *really* want to do it anyway, `nohup lokid &` will do the job. (The Windows service control code, which is probably seldom used, is kept because it seems potentially useful for Windows users). - Many of the `t_whatever` classes in daemon/* are just deleted (mostly done in #1138); each one was a bunch of junk code that wraps 3-4 lines but forces an extra layer (not even a generic abstraction, just a useless wrapper) for no good reason and made the daemon code painfully hard to understand and work with. - All of the remaining `t_whatever` classes in daemon/* are either renamed to `whatever` (because prefixing every class with `t_` is moronic). - Some stupid related code (e.g. epee's command handler returning an unsuitable "usage" string that has to be string modified into what we want) was replaced with more generic, useful code. - Replaced boost mutexes/cvs with std ones in epee command handler, and deleted some commented out code. - The `--public-node` option handling was terrible: it was being handled in main, but main doesn't know anything about options, so then it forced it through the spaghetti objects *beside* the pack of all options that got passed along. Moved it to a more sane location (core_rpc_server) and parse it out with some sanity. - Changed a bunch of std::bind's to lambdas because, at least for small lambdas (i.e. with only one-or-two pointers for captures) they will generally be more efficient as the values can be stored in std::function's without any memory allocations.
2020-04-02 22:38:52 +02:00
std::mutex m_request_mutex;
std::mutex m_response_mutex;
std::condition_variable m_request_cv;
std::condition_variable m_response_cv;
2014-03-20 12:46:11 +01:00
};
class async_console_handler
2014-03-03 23:07:58 +01:00
{
2014-03-20 12:46:11 +01:00
public:
async_console_handler()
2014-03-03 23:07:58 +01:00
{
2014-03-20 12:46:11 +01:00
}
2014-03-03 23:07:58 +01:00
template<class t_server, class chain_handler>
bool run(t_server* psrv, chain_handler ch_handler, std::function<std::string()> prompt, const std::string& usage = "")
{
return run(prompt, usage, [&](const std::string& cmd) { return ch_handler(psrv, cmd); }, [&] { psrv->send_stop_signal(); });
}
2014-03-20 12:46:11 +01:00
template<class chain_handler>
bool run(chain_handler ch_handler, std::function<std::string()> prompt, const std::string& usage = "", std::function<void()> exit_handler = NULL)
2014-03-20 12:46:11 +01:00
{
2020-06-22 02:17:04 +02:00
return run(prompt, usage, [&](const std::optional<std::string>& cmd) { return ch_handler(cmd); }, exit_handler);
2014-03-20 12:46:11 +01:00
}
void stop()
{
m_running = false;
2014-03-20 12:46:11 +01:00
m_stdin_reader.stop();
}
void cancel()
{
m_cancel = true;
m_stdin_reader.cancel();
}
void print_prompt()
{
std::string prompt = m_prompt();
if (!prompt.empty())
{
#ifdef HAVE_READLINE
std::string color_prompt = "\001\033[1;33m\002" + prompt;
if (' ' != prompt.back())
color_prompt += " ";
color_prompt += "\001\033[0m\002";
m_stdin_reader.get_readline_buffer().set_prompt(color_prompt);
#else
Change logging to easylogging++ This replaces the epee and data_loggers logging systems with a single one, and also adds filename:line and explicit severity levels. Categories may be defined, and logging severity set by category (or set of categories). epee style 0-4 log level maps to a sensible severity configuration. Log files now also rotate when reaching 100 MB. To select which logs to output, use the MONERO_LOGS environment variable, with a comma separated list of categories (globs are supported), with their requested severity level after a colon. If a log matches more than one such setting, the last one in the configuration string applies. A few examples: This one is (mostly) silent, only outputting fatal errors: MONERO_LOGS=*:FATAL This one is very verbose: MONERO_LOGS=*:TRACE This one is totally silent (logwise): MONERO_LOGS="" This one outputs all errors and warnings, except for the "verify" category, which prints just fatal errors (the verify category is used for logs about incoming transactions and blocks, and it is expected that some/many will fail to verify, hence we don't want the spam): MONERO_LOGS=*:WARNING,verify:FATAL Log levels are, in decreasing order of priority: FATAL, ERROR, WARNING, INFO, DEBUG, TRACE Subcategories may be added using prefixes and globs. This example will output net.p2p logs at the TRACE level, but all other net* logs only at INFO: MONERO_LOGS=*:ERROR,net*:INFO,net.p2p:TRACE Logs which are intended for the user (which Monero was using a lot through epee, but really isn't a nice way to go things) should use the "global" category. There are a few helper macros for using this category, eg: MGINFO("this shows up by default") or MGINFO_RED("this is red"), to try to keep a similar look and feel for now. Existing epee log macros still exist, and map to the new log levels, but since they're used as a "user facing" UI element as much as a logging system, they often don't map well to log severities (ie, a log level 0 log may be an error, or may be something we want the user to see, such as an important info). In those cases, I tried to use the new macros. In other cases, I left the existing macros in. When modifying logs, it is probably best to switch to the new macros with explicit levels. The --log-level options and set_log commands now also accept category settings, in addition to the epee style log levels.
2017-01-01 17:34:23 +01:00
epee::set_console_color(epee::console_color_yellow, true);
std::cout << prompt;
if (' ' != prompt.back())
std::cout << ' ';
Change logging to easylogging++ This replaces the epee and data_loggers logging systems with a single one, and also adds filename:line and explicit severity levels. Categories may be defined, and logging severity set by category (or set of categories). epee style 0-4 log level maps to a sensible severity configuration. Log files now also rotate when reaching 100 MB. To select which logs to output, use the MONERO_LOGS environment variable, with a comma separated list of categories (globs are supported), with their requested severity level after a colon. If a log matches more than one such setting, the last one in the configuration string applies. A few examples: This one is (mostly) silent, only outputting fatal errors: MONERO_LOGS=*:FATAL This one is very verbose: MONERO_LOGS=*:TRACE This one is totally silent (logwise): MONERO_LOGS="" This one outputs all errors and warnings, except for the "verify" category, which prints just fatal errors (the verify category is used for logs about incoming transactions and blocks, and it is expected that some/many will fail to verify, hence we don't want the spam): MONERO_LOGS=*:WARNING,verify:FATAL Log levels are, in decreasing order of priority: FATAL, ERROR, WARNING, INFO, DEBUG, TRACE Subcategories may be added using prefixes and globs. This example will output net.p2p logs at the TRACE level, but all other net* logs only at INFO: MONERO_LOGS=*:ERROR,net*:INFO,net.p2p:TRACE Logs which are intended for the user (which Monero was using a lot through epee, but really isn't a nice way to go things) should use the "global" category. There are a few helper macros for using this category, eg: MGINFO("this shows up by default") or MGINFO_RED("this is red"), to try to keep a similar look and feel for now. Existing epee log macros still exist, and map to the new log levels, but since they're used as a "user facing" UI element as much as a logging system, they often don't map well to log severities (ie, a log level 0 log may be an error, or may be something we want the user to see, such as an important info). In those cases, I tried to use the new macros. In other cases, I left the existing macros in. When modifying logs, it is probably best to switch to the new macros with explicit levels. The --log-level options and set_log commands now also accept category settings, in addition to the epee style log levels.
2017-01-01 17:34:23 +01:00
epee::reset_console_color();
std::cout.flush();
#endif
}
}
2014-03-20 12:46:11 +01:00
private:
template<typename t_cmd_handler>
bool run(std::function<std::string()> prompt, const std::string& usage, const t_cmd_handler& cmd_handler, std::function<void()> exit_handler)
2014-03-20 12:46:11 +01:00
{
bool continue_handle = true;
m_prompt = prompt;
2014-03-20 12:46:11 +01:00
while(continue_handle)
2014-03-03 23:07:58 +01:00
{
try
{
if (!m_running)
{
break;
}
print_prompt();
2014-03-20 12:46:11 +01:00
std::string command;
bool get_line_ret = m_stdin_reader.get_line(command);
if (!m_running)
break;
if (m_stdin_reader.eos())
{
MGINFO("EOF on stdin, exiting");
std::cout << std::endl;
break;
}
if (m_cancel)
{
MDEBUG("Input cancelled");
2020-06-22 02:17:04 +02:00
cmd_handler(std::nullopt);
m_cancel = false;
continue;
}
if (!get_line_ret)
{
Change logging to easylogging++ This replaces the epee and data_loggers logging systems with a single one, and also adds filename:line and explicit severity levels. Categories may be defined, and logging severity set by category (or set of categories). epee style 0-4 log level maps to a sensible severity configuration. Log files now also rotate when reaching 100 MB. To select which logs to output, use the MONERO_LOGS environment variable, with a comma separated list of categories (globs are supported), with their requested severity level after a colon. If a log matches more than one such setting, the last one in the configuration string applies. A few examples: This one is (mostly) silent, only outputting fatal errors: MONERO_LOGS=*:FATAL This one is very verbose: MONERO_LOGS=*:TRACE This one is totally silent (logwise): MONERO_LOGS="" This one outputs all errors and warnings, except for the "verify" category, which prints just fatal errors (the verify category is used for logs about incoming transactions and blocks, and it is expected that some/many will fail to verify, hence we don't want the spam): MONERO_LOGS=*:WARNING,verify:FATAL Log levels are, in decreasing order of priority: FATAL, ERROR, WARNING, INFO, DEBUG, TRACE Subcategories may be added using prefixes and globs. This example will output net.p2p logs at the TRACE level, but all other net* logs only at INFO: MONERO_LOGS=*:ERROR,net*:INFO,net.p2p:TRACE Logs which are intended for the user (which Monero was using a lot through epee, but really isn't a nice way to go things) should use the "global" category. There are a few helper macros for using this category, eg: MGINFO("this shows up by default") or MGINFO_RED("this is red"), to try to keep a similar look and feel for now. Existing epee log macros still exist, and map to the new log levels, but since they're used as a "user facing" UI element as much as a logging system, they often don't map well to log severities (ie, a log level 0 log may be an error, or may be something we want the user to see, such as an important info). In those cases, I tried to use the new macros. In other cases, I left the existing macros in. When modifying logs, it is probably best to switch to the new macros with explicit levels. The --log-level options and set_log commands now also accept category settings, in addition to the epee style log levels.
2017-01-01 17:34:23 +01:00
MERROR("Failed to read line.");
}
string_tools::trim(command);
2014-03-20 12:46:11 +01:00
LOG_PRINT_L2("Read command: " << command);
if (command.empty())
{
continue;
}
else if(0 == command.compare("exit") || 0 == command.compare("q"))
{
continue_handle = false;
}
else
{
cmd_handler(command);
}
}
catch (const std::exception &ex)
2014-03-20 12:46:11 +01:00
{
LOG_ERROR("Exception at [console_handler], what=" << ex.what());
2014-03-03 23:07:58 +01:00
}
}
if (exit_handler)
exit_handler();
2014-03-20 12:46:11 +01:00
return true;
2014-03-03 23:07:58 +01:00
}
2014-03-20 12:46:11 +01:00
private:
async_stdin_reader m_stdin_reader;
std::atomic<bool> m_running = {true};
std::atomic<bool> m_cancel = {false};
std::function<std::string()> m_prompt;
2014-03-20 12:46:11 +01:00
};
2014-03-03 23:07:58 +01:00
class command_handler {
2014-03-20 12:46:11 +01:00
public:
using callback = std::function<bool(const std::vector<std::string> &)>;
using empty_callback = std::function<bool()>;
using lookup = std::map<std::string, std::pair<callback, std::pair<std::string, std::string>>>;
daemon & daemonize overhaul This commit continues the complete replacement of the spaghetti code mess that was inside daemon/ and daemonize/ which started in #1138, and looked like a entry level Java programmer threw up inside the code base. This greatly simplifies it, removing a whole pile of useless abstraction layers that don't actually abstract anything, and results in considerably simpler code. (Many of the changes here were also carried out in #1138; this commit updates them with the merged result which amends some things from that PR and goes further in some places). In detail: - the `--detach` (and related `--pidfile`) options are gone. (--detach is still handled, but now just prints a fatal error). Detaching a process is an archaic unix mechanism that has no place on a modern system. If you *really* want to do it anyway, `nohup lokid &` will do the job. (The Windows service control code, which is probably seldom used, is kept because it seems potentially useful for Windows users). - Many of the `t_whatever` classes in daemon/* are just deleted (mostly done in #1138); each one was a bunch of junk code that wraps 3-4 lines but forces an extra layer (not even a generic abstraction, just a useless wrapper) for no good reason and made the daemon code painfully hard to understand and work with. - All of the remaining `t_whatever` classes in daemon/* are either renamed to `whatever` (because prefixing every class with `t_` is moronic). - Some stupid related code (e.g. epee's command handler returning an unsuitable "usage" string that has to be string modified into what we want) was replaced with more generic, useful code. - Replaced boost mutexes/cvs with std ones in epee command handler, and deleted some commented out code. - The `--public-node` option handling was terrible: it was being handled in main, but main doesn't know anything about options, so then it forced it through the spaghetti objects *beside* the pack of all options that got passed along. Moved it to a more sane location (core_rpc_server) and parse it out with some sanity. - Changed a bunch of std::bind's to lambdas because, at least for small lambdas (i.e. with only one-or-two pointers for captures) they will generally be more efficient as the values can be stored in std::function's without any memory allocations.
2020-04-02 22:38:52 +02:00
/// Go through registered commands in sorted order, call the function with three string
/// arguments: command name, usage, and description.
template <typename Function>
void for_each(Function f)
2014-03-03 23:07:58 +01:00
{
daemon & daemonize overhaul This commit continues the complete replacement of the spaghetti code mess that was inside daemon/ and daemonize/ which started in #1138, and looked like a entry level Java programmer threw up inside the code base. This greatly simplifies it, removing a whole pile of useless abstraction layers that don't actually abstract anything, and results in considerably simpler code. (Many of the changes here were also carried out in #1138; this commit updates them with the merged result which amends some things from that PR and goes further in some places). In detail: - the `--detach` (and related `--pidfile`) options are gone. (--detach is still handled, but now just prints a fatal error). Detaching a process is an archaic unix mechanism that has no place on a modern system. If you *really* want to do it anyway, `nohup lokid &` will do the job. (The Windows service control code, which is probably seldom used, is kept because it seems potentially useful for Windows users). - Many of the `t_whatever` classes in daemon/* are just deleted (mostly done in #1138); each one was a bunch of junk code that wraps 3-4 lines but forces an extra layer (not even a generic abstraction, just a useless wrapper) for no good reason and made the daemon code painfully hard to understand and work with. - All of the remaining `t_whatever` classes in daemon/* are either renamed to `whatever` (because prefixing every class with `t_` is moronic). - Some stupid related code (e.g. epee's command handler returning an unsuitable "usage" string that has to be string modified into what we want) was replaced with more generic, useful code. - Replaced boost mutexes/cvs with std ones in epee command handler, and deleted some commented out code. - The `--public-node` option handling was terrible: it was being handled in main, but main doesn't know anything about options, so then it forced it through the spaghetti objects *beside* the pack of all options that got passed along. Moved it to a more sane location (core_rpc_server) and parse it out with some sanity. - Changed a bunch of std::bind's to lambdas because, at least for small lambdas (i.e. with only one-or-two pointers for captures) they will generally be more efficient as the values can be stored in std::function's without any memory allocations.
2020-04-02 22:38:52 +02:00
for (const auto& x : m_command_handlers)
f(x.first, x.second.second.first, x.second.second.second);
2014-03-03 23:07:58 +01:00
}
daemon & daemonize overhaul This commit continues the complete replacement of the spaghetti code mess that was inside daemon/ and daemonize/ which started in #1138, and looked like a entry level Java programmer threw up inside the code base. This greatly simplifies it, removing a whole pile of useless abstraction layers that don't actually abstract anything, and results in considerably simpler code. (Many of the changes here were also carried out in #1138; this commit updates them with the merged result which amends some things from that PR and goes further in some places). In detail: - the `--detach` (and related `--pidfile`) options are gone. (--detach is still handled, but now just prints a fatal error). Detaching a process is an archaic unix mechanism that has no place on a modern system. If you *really* want to do it anyway, `nohup lokid &` will do the job. (The Windows service control code, which is probably seldom used, is kept because it seems potentially useful for Windows users). - Many of the `t_whatever` classes in daemon/* are just deleted (mostly done in #1138); each one was a bunch of junk code that wraps 3-4 lines but forces an extra layer (not even a generic abstraction, just a useless wrapper) for no good reason and made the daemon code painfully hard to understand and work with. - All of the remaining `t_whatever` classes in daemon/* are either renamed to `whatever` (because prefixing every class with `t_` is moronic). - Some stupid related code (e.g. epee's command handler returning an unsuitable "usage" string that has to be string modified into what we want) was replaced with more generic, useful code. - Replaced boost mutexes/cvs with std ones in epee command handler, and deleted some commented out code. - The `--public-node` option handling was terrible: it was being handled in main, but main doesn't know anything about options, so then it forced it through the spaghetti objects *beside* the pack of all options that got passed along. Moved it to a more sane location (core_rpc_server) and parse it out with some sanity. - Changed a bunch of std::bind's to lambdas because, at least for small lambdas (i.e. with only one-or-two pointers for captures) they will generally be more efficient as the values can be stored in std::function's without any memory allocations.
2020-04-02 22:38:52 +02:00
/// Returns {usage, description} for a given command.
2017-11-22 13:53:18 +01:00
std::pair<std::string, std::string> get_documentation(const std::vector<std::string>& cmd)
{
if(cmd.empty())
daemon & daemonize overhaul This commit continues the complete replacement of the spaghetti code mess that was inside daemon/ and daemonize/ which started in #1138, and looked like a entry level Java programmer threw up inside the code base. This greatly simplifies it, removing a whole pile of useless abstraction layers that don't actually abstract anything, and results in considerably simpler code. (Many of the changes here were also carried out in #1138; this commit updates them with the merged result which amends some things from that PR and goes further in some places). In detail: - the `--detach` (and related `--pidfile`) options are gone. (--detach is still handled, but now just prints a fatal error). Detaching a process is an archaic unix mechanism that has no place on a modern system. If you *really* want to do it anyway, `nohup lokid &` will do the job. (The Windows service control code, which is probably seldom used, is kept because it seems potentially useful for Windows users). - Many of the `t_whatever` classes in daemon/* are just deleted (mostly done in #1138); each one was a bunch of junk code that wraps 3-4 lines but forces an extra layer (not even a generic abstraction, just a useless wrapper) for no good reason and made the daemon code painfully hard to understand and work with. - All of the remaining `t_whatever` classes in daemon/* are either renamed to `whatever` (because prefixing every class with `t_` is moronic). - Some stupid related code (e.g. epee's command handler returning an unsuitable "usage" string that has to be string modified into what we want) was replaced with more generic, useful code. - Replaced boost mutexes/cvs with std ones in epee command handler, and deleted some commented out code. - The `--public-node` option handling was terrible: it was being handled in main, but main doesn't know anything about options, so then it forced it through the spaghetti objects *beside* the pack of all options that got passed along. Moved it to a more sane location (core_rpc_server) and parse it out with some sanity. - Changed a bunch of std::bind's to lambdas because, at least for small lambdas (i.e. with only one-or-two pointers for captures) they will generally be more efficient as the values can be stored in std::function's without any memory allocations.
2020-04-02 22:38:52 +02:00
return {"", ""};
2017-11-22 13:53:18 +01:00
auto it = m_command_handlers.find(cmd.front());
if(it == m_command_handlers.end())
daemon & daemonize overhaul This commit continues the complete replacement of the spaghetti code mess that was inside daemon/ and daemonize/ which started in #1138, and looked like a entry level Java programmer threw up inside the code base. This greatly simplifies it, removing a whole pile of useless abstraction layers that don't actually abstract anything, and results in considerably simpler code. (Many of the changes here were also carried out in #1138; this commit updates them with the merged result which amends some things from that PR and goes further in some places). In detail: - the `--detach` (and related `--pidfile`) options are gone. (--detach is still handled, but now just prints a fatal error). Detaching a process is an archaic unix mechanism that has no place on a modern system. If you *really* want to do it anyway, `nohup lokid &` will do the job. (The Windows service control code, which is probably seldom used, is kept because it seems potentially useful for Windows users). - Many of the `t_whatever` classes in daemon/* are just deleted (mostly done in #1138); each one was a bunch of junk code that wraps 3-4 lines but forces an extra layer (not even a generic abstraction, just a useless wrapper) for no good reason and made the daemon code painfully hard to understand and work with. - All of the remaining `t_whatever` classes in daemon/* are either renamed to `whatever` (because prefixing every class with `t_` is moronic). - Some stupid related code (e.g. epee's command handler returning an unsuitable "usage" string that has to be string modified into what we want) was replaced with more generic, useful code. - Replaced boost mutexes/cvs with std ones in epee command handler, and deleted some commented out code. - The `--public-node` option handling was terrible: it was being handled in main, but main doesn't know anything about options, so then it forced it through the spaghetti objects *beside* the pack of all options that got passed along. Moved it to a more sane location (core_rpc_server) and parse it out with some sanity. - Changed a bunch of std::bind's to lambdas because, at least for small lambdas (i.e. with only one-or-two pointers for captures) they will generally be more efficient as the values can be stored in std::function's without any memory allocations.
2020-04-02 22:38:52 +02:00
return {"", ""};
2017-11-22 13:53:18 +01:00
return it->second.second;
}
using pre_handler_callback = std::function<std::any(const std::string& cmd)>;
using post_handler_callback = std::function<void(const std::string& cmd, bool& handler_result, std::any pre_handler_result)>;
/// Sets a pre-handler than runs immediately before any handler set up with `set_handler`.
/// Called with the command name. If the handler returns a value it will be stored in a
/// `std::any` and then passed into the `post_handler`. Pre- and post-handlers are only invoked
/// on valid commands.
template <typename Callback>
void pre_handler(Callback handler)
{
using Return = decltype(handler(""s));
if constexpr (std::is_void_v<Return>)
m_pre_handler = [f=std::move(handler)](const std::string& cmd) { f(cmd); return std::any{}; };
else if constexpr (std::is_same_v<Return, std::any>)
m_pre_handler = handler;
else
m_pre_handler = [f=std::move(handler)](const std::string& cmd) -> std::any { return f(cmd); };
}
/// Sets a post-handler that runs immediately after a handler set up with `set_handler`. Takes
/// three arguments:
/// - the command name
/// - a `bool&` containing the result returned by the handler (which can be modified by the post
/// handler to affect the callback return, if desired)
/// - an `std::any` containing the result of the pre-handler. (If not pre-handler was set up or
/// the pre-handler has a void return, the std::any will be empty).
///
/// The post handler is not invoked at all if the command handler throws an exception.
void post_handler(post_handler_callback handler)
{
m_post_handler = std::move(handler);
}
daemon & daemonize overhaul This commit continues the complete replacement of the spaghetti code mess that was inside daemon/ and daemonize/ which started in #1138, and looked like a entry level Java programmer threw up inside the code base. This greatly simplifies it, removing a whole pile of useless abstraction layers that don't actually abstract anything, and results in considerably simpler code. (Many of the changes here were also carried out in #1138; this commit updates them with the merged result which amends some things from that PR and goes further in some places). In detail: - the `--detach` (and related `--pidfile`) options are gone. (--detach is still handled, but now just prints a fatal error). Detaching a process is an archaic unix mechanism that has no place on a modern system. If you *really* want to do it anyway, `nohup lokid &` will do the job. (The Windows service control code, which is probably seldom used, is kept because it seems potentially useful for Windows users). - Many of the `t_whatever` classes in daemon/* are just deleted (mostly done in #1138); each one was a bunch of junk code that wraps 3-4 lines but forces an extra layer (not even a generic abstraction, just a useless wrapper) for no good reason and made the daemon code painfully hard to understand and work with. - All of the remaining `t_whatever` classes in daemon/* are either renamed to `whatever` (because prefixing every class with `t_` is moronic). - Some stupid related code (e.g. epee's command handler returning an unsuitable "usage" string that has to be string modified into what we want) was replaced with more generic, useful code. - Replaced boost mutexes/cvs with std ones in epee command handler, and deleted some commented out code. - The `--public-node` option handling was terrible: it was being handled in main, but main doesn't know anything about options, so then it forced it through the spaghetti objects *beside* the pack of all options that got passed along. Moved it to a more sane location (core_rpc_server) and parse it out with some sanity. - Changed a bunch of std::bind's to lambdas because, at least for small lambdas (i.e. with only one-or-two pointers for captures) they will generally be more efficient as the values can be stored in std::function's without any memory allocations.
2020-04-02 22:38:52 +02:00
void set_handler(const std::string& cmd, callback hndlr, std::string usage = "", std::string description = "")
2014-03-03 23:07:58 +01:00
{
lookup::mapped_type & vt = m_command_handlers[cmd];
daemon & daemonize overhaul This commit continues the complete replacement of the spaghetti code mess that was inside daemon/ and daemonize/ which started in #1138, and looked like a entry level Java programmer threw up inside the code base. This greatly simplifies it, removing a whole pile of useless abstraction layers that don't actually abstract anything, and results in considerably simpler code. (Many of the changes here were also carried out in #1138; this commit updates them with the merged result which amends some things from that PR and goes further in some places). In detail: - the `--detach` (and related `--pidfile`) options are gone. (--detach is still handled, but now just prints a fatal error). Detaching a process is an archaic unix mechanism that has no place on a modern system. If you *really* want to do it anyway, `nohup lokid &` will do the job. (The Windows service control code, which is probably seldom used, is kept because it seems potentially useful for Windows users). - Many of the `t_whatever` classes in daemon/* are just deleted (mostly done in #1138); each one was a bunch of junk code that wraps 3-4 lines but forces an extra layer (not even a generic abstraction, just a useless wrapper) for no good reason and made the daemon code painfully hard to understand and work with. - All of the remaining `t_whatever` classes in daemon/* are either renamed to `whatever` (because prefixing every class with `t_` is moronic). - Some stupid related code (e.g. epee's command handler returning an unsuitable "usage" string that has to be string modified into what we want) was replaced with more generic, useful code. - Replaced boost mutexes/cvs with std ones in epee command handler, and deleted some commented out code. - The `--public-node` option handling was terrible: it was being handled in main, but main doesn't know anything about options, so then it forced it through the spaghetti objects *beside* the pack of all options that got passed along. Moved it to a more sane location (core_rpc_server) and parse it out with some sanity. - Changed a bunch of std::bind's to lambdas because, at least for small lambdas (i.e. with only one-or-two pointers for captures) they will generally be more efficient as the values can be stored in std::function's without any memory allocations.
2020-04-02 22:38:52 +02:00
vt.first = std::move(hndlr);
if (description.empty())
vt.second = {cmd, std::move(usage)};
else
vt.second = {std::move(usage), std::move(description)};
#ifdef HAVE_READLINE
rdln::readline_buffer::add_completion(cmd);
#endif
2014-03-03 23:07:58 +01:00
}
/// Throws invalid_command on bad command with what() set to the command name, otherwise
RPC overhaul High-level details: This redesigns the RPC layer to make it much easier to work with, decouples it from an embedded HTTP server, and gets the vast majority of the RPC serialization and dispatch code out of a very commonly included header. There is unfortunately rather a lot of interconnected code here that cannot be easily separated out into separate commits. The full details of what happens here are as follows: Major details: - All of the RPC code is now in a `cryptonote::rpc` namespace; this renames quite a bit to be less verbose: e.g. CORE_RPC_STATUS_OK becomes `rpc::STATUS_OK`, and `cryptonote::COMMAND_RPC_SOME_LONG_NAME` becomes `rpc::SOME_LONG_NAME` (or just SOME_LONG_NAME for code already working in the `rpc` namespace). - `core_rpc_server` is now completely decoupled from providing any request protocol: it is now *just* the core RPC call handler. - The HTTP RPC interface now lives in a new rpc/http_server.h; this code handles listening for HTTP requests and dispatching them to core_rpc_server, then sending the results back to the caller. - There is similarly a rpc/lmq_server.h for LMQ RPC code; more details on this (and other LMQ specifics) below. - RPC implementing code now returns the response object and throws when things go wrong which simplifies much of the rpc error handling. They can throw anything; generic exceptions get logged and a generic "internal error" message gets returned to the caller, but there is also an `rpc_error` class to return an error code and message used by some json-rpc commands. - RPC implementing functions now overload `core_rpc_server::invoke` following the pattern: RPC_BLAH_BLAH::response core_rpc_server::invoke(RPC_BLAH_BLAH::request&& req, rpc_context context); This overloading makes the code vastly simpler: all instantiations are now done with a small amount of generic instantiation code in a single .cpp rather than needing to go to hell and back with a nest of epee macros in a core header. - each RPC endpoint is now defined by the RPC types themselves, including its accessible names and permissions, in core_rpc_server_commands_defs.h: - every RPC structure now has a static `names()` function that returns the names by which the end point is accessible. (The first one is the primary, the others are for deprecated aliases). - RPC command wrappers define their permissions and type by inheriting from special tag classes: - rpc::RPC_COMMAND is a basic, admin-only, JSON command, available via JSON RPC. *All* JSON commands are now available via JSON RPC, instead of the previous mix of some being at /foo and others at /json_rpc. (Ones that were previously at /foo are still there for backwards compatibility; see `rpc::LEGACY` below). - rpc::PUBLIC specifies that the command should be available via a restricted RPC connection. - rpc::BINARY specifies that the command is not JSON, but rather is accessible as /name and takes and returns values in the magic epee binary "portable storage" (lol) data format. - rpc::LEGACY specifies that the command should be available via the non-json-rpc interface at `/name` for backwards compatibility (in addition to the JSON-RPC interface). - some epee serialization got unwrapped and de-templatized so that it can be moved into a .cpp file with just declarations in the .h. (This makes a *huge* difference for core_rpc_server_commands_defs.h and for every compilation unit that includes it which previously had to compile all the serialization code and then throw all by one copy away at link time). This required some new macros so as to not break a ton of places that will use the old way putting everything in the headers; The RPC code uses this as does a few other places; there are comments in contrib/epee/include/serialization/keyvalue_serialization.h as to how to use it. - Detemplatized a bunch of epee/storages code. Most of it should have have been using templates at all (because it can only ever be called with one type!), and now it isn't. This broke some things that didn't properly compile because of missing headers or (in one case) a messed up circular dependency. - Significantly simplified a bunch of over-templatized serialization code. - All RPC serialization definitions is now out of core_rpc_server_commands_defs.h and into a single .cpp file (core_rpc_server_commands_defs.cpp). - core RPC no longer uses the disgusting BEGIN_URI_MAP2/MAP_URI_BLAH_BLAH macros. This was a terrible design that forced slamming tons of code into a common header that didn't need to be there. - epee::struct_init is gone. It was a horrible hack that instiated multiple templates just so the coder could be so lazy and write `some_type var;` instead of properly value initializing with `some_type var{};`. - Removed a bunch of useless crap from epee. In particular, forcing extra template instantiations all over the place in order to nest return objects inside JSON RPC values is no longer needed, as are a bunch of stuff related to the above de-macroization of the code. - get_all_service_nodes, get_service_nodes, and get_n_service_nodes are now combined into a single `get_service_nodes` (with deprecated aliases for the others), which eliminates a fair amount of duplication. The biggest obstacle here was getting the requested fields reference passed through: this is now done by a new ability to stash a context in the serialization object that can be retrieved by a sub-serialized type. LMQ-specifics: - The LokiMQ instance moves into `cryptonote::core` rather than being inside cryptonote_protocol. Currently the instance is used both for qnet and rpc calls (and so needs to be in a common place), but I also intend future PRs to use the batching code for job processing (replacing the current threaded job queue). - rpc/lmq_server.h handles the actual LMQ-request-to-core-RPC glue. Unlike http_server it isn't technically running the whole LMQ stack from here, but the parallel name with http_server seemed appropriate. - All RPC endpoints are supported by LMQ under the same names as defined generically, but prefixed with `rpc.` for public commands and `admin.` for restricted ones. - service node keys are now always available, even when not running in `--service-node` mode: this is because we want the x25519 key for being able to offer CURVE encryption for lmq RPC end-points, and because it doesn't hurt to have them available all the time. In the RPC layer this is now called "get_service_keys" (with "get_service_node_key" as an alias) since they aren't strictly only for service nodes. This also means code needs to check m_service_node, and not m_service_node_keys, to tell if it is running as a service node. (This is also easier to notice because m_service_node_keys got renamed to `m_service_keys`). - Added block and mempool monitoring LMQ RPC endpoints: `sub.block` and `sub.mempool` subscribes the connection for new block and new mempool TX notifications. The latter can notify on just blink txes, or all new mempool txes (but only new ones -- txes dumped from a block don't trigger it). The client gets pushed a [`notify.block`, `height`, `hash`] or [`notify.tx`, `txhash`, `blob`] message when something arrives. Minor details: - rpc::version_t is now a {major,minor} pair. Forcing everyone to pack and unpack a uint32_t was gross. - Changed some macros to constexprs (e.g. CORE_RPC_ERROR_CODE_...). (This immediately revealed a couple of bugs in the RPC code that was assigning CORE_RPC_ERROR_CODE_... to a string, and it worked because the macro allows implicit conversion to a char). - De-templatizing useless templates in epee (i.e. a bunch of templated types that were never invoked with different types) revealed a painful circular dependency between epee and non-epee code for tor_address and i2p_address. This crap is now handled in a suitably named `net/epee_network_address_hack.cpp` hack because it really isn't trivial to extricate this mess. - Removed `epee/include/serialization/serialize_base.h`. Amazingly the code somehow still all works perfectly with this previously vital header removed. - Removed bitrotted, unused epee "crypted_storage" and "gzipped_inmemstorage" code. - Replaced a bunch of epee::misc_utils::auto_scope_leave_caller with LOKI_DEFERs. The epee version involves quite a bit more instantiation and is ugly as sin. Also made the `loki::defer` class invokable for some edge cases that need calling before destruction in particular conditions. - Moved the systemd code around; it makes much more sense to do the systemd started notification as in daemon.cpp as late as possible rather than in core (when we can still have startup failures, e.g. if the RPC layer can't start). - Made the systemd short status string available in the get_info RPC (and no longer require building with systemd). - during startup, print (only) the x25519 when not in SN mode, and continue to print all three when in SN mode. - DRYed out some RPC implementation code (such as set_limit) - Made wallet_rpc stop using a raw m_wallet pointer
2020-04-28 01:25:43 +02:00
/// returns the result of the command (true generally means success, false means failure).
struct invalid_command : std::invalid_argument { using std::invalid_argument::invalid_argument; };
daemon & daemonize overhaul This commit continues the complete replacement of the spaghetti code mess that was inside daemon/ and daemonize/ which started in #1138, and looked like a entry level Java programmer threw up inside the code base. This greatly simplifies it, removing a whole pile of useless abstraction layers that don't actually abstract anything, and results in considerably simpler code. (Many of the changes here were also carried out in #1138; this commit updates them with the merged result which amends some things from that PR and goes further in some places). In detail: - the `--detach` (and related `--pidfile`) options are gone. (--detach is still handled, but now just prints a fatal error). Detaching a process is an archaic unix mechanism that has no place on a modern system. If you *really* want to do it anyway, `nohup lokid &` will do the job. (The Windows service control code, which is probably seldom used, is kept because it seems potentially useful for Windows users). - Many of the `t_whatever` classes in daemon/* are just deleted (mostly done in #1138); each one was a bunch of junk code that wraps 3-4 lines but forces an extra layer (not even a generic abstraction, just a useless wrapper) for no good reason and made the daemon code painfully hard to understand and work with. - All of the remaining `t_whatever` classes in daemon/* are either renamed to `whatever` (because prefixing every class with `t_` is moronic). - Some stupid related code (e.g. epee's command handler returning an unsuitable "usage" string that has to be string modified into what we want) was replaced with more generic, useful code. - Replaced boost mutexes/cvs with std ones in epee command handler, and deleted some commented out code. - The `--public-node` option handling was terrible: it was being handled in main, but main doesn't know anything about options, so then it forced it through the spaghetti objects *beside* the pack of all options that got passed along. Moved it to a more sane location (core_rpc_server) and parse it out with some sanity. - Changed a bunch of std::bind's to lambdas because, at least for small lambdas (i.e. with only one-or-two pointers for captures) they will generally be more efficient as the values can be stored in std::function's without any memory allocations.
2020-04-02 22:38:52 +02:00
bool process_command(const std::vector<std::string>& cmd)
2014-03-03 23:07:58 +01:00
{
if(!cmd.size())
throw invalid_command{"(empty)"};
2014-03-03 23:07:58 +01:00
auto it = m_command_handlers.find(cmd.front());
RPC overhaul High-level details: This redesigns the RPC layer to make it much easier to work with, decouples it from an embedded HTTP server, and gets the vast majority of the RPC serialization and dispatch code out of a very commonly included header. There is unfortunately rather a lot of interconnected code here that cannot be easily separated out into separate commits. The full details of what happens here are as follows: Major details: - All of the RPC code is now in a `cryptonote::rpc` namespace; this renames quite a bit to be less verbose: e.g. CORE_RPC_STATUS_OK becomes `rpc::STATUS_OK`, and `cryptonote::COMMAND_RPC_SOME_LONG_NAME` becomes `rpc::SOME_LONG_NAME` (or just SOME_LONG_NAME for code already working in the `rpc` namespace). - `core_rpc_server` is now completely decoupled from providing any request protocol: it is now *just* the core RPC call handler. - The HTTP RPC interface now lives in a new rpc/http_server.h; this code handles listening for HTTP requests and dispatching them to core_rpc_server, then sending the results back to the caller. - There is similarly a rpc/lmq_server.h for LMQ RPC code; more details on this (and other LMQ specifics) below. - RPC implementing code now returns the response object and throws when things go wrong which simplifies much of the rpc error handling. They can throw anything; generic exceptions get logged and a generic "internal error" message gets returned to the caller, but there is also an `rpc_error` class to return an error code and message used by some json-rpc commands. - RPC implementing functions now overload `core_rpc_server::invoke` following the pattern: RPC_BLAH_BLAH::response core_rpc_server::invoke(RPC_BLAH_BLAH::request&& req, rpc_context context); This overloading makes the code vastly simpler: all instantiations are now done with a small amount of generic instantiation code in a single .cpp rather than needing to go to hell and back with a nest of epee macros in a core header. - each RPC endpoint is now defined by the RPC types themselves, including its accessible names and permissions, in core_rpc_server_commands_defs.h: - every RPC structure now has a static `names()` function that returns the names by which the end point is accessible. (The first one is the primary, the others are for deprecated aliases). - RPC command wrappers define their permissions and type by inheriting from special tag classes: - rpc::RPC_COMMAND is a basic, admin-only, JSON command, available via JSON RPC. *All* JSON commands are now available via JSON RPC, instead of the previous mix of some being at /foo and others at /json_rpc. (Ones that were previously at /foo are still there for backwards compatibility; see `rpc::LEGACY` below). - rpc::PUBLIC specifies that the command should be available via a restricted RPC connection. - rpc::BINARY specifies that the command is not JSON, but rather is accessible as /name and takes and returns values in the magic epee binary "portable storage" (lol) data format. - rpc::LEGACY specifies that the command should be available via the non-json-rpc interface at `/name` for backwards compatibility (in addition to the JSON-RPC interface). - some epee serialization got unwrapped and de-templatized so that it can be moved into a .cpp file with just declarations in the .h. (This makes a *huge* difference for core_rpc_server_commands_defs.h and for every compilation unit that includes it which previously had to compile all the serialization code and then throw all by one copy away at link time). This required some new macros so as to not break a ton of places that will use the old way putting everything in the headers; The RPC code uses this as does a few other places; there are comments in contrib/epee/include/serialization/keyvalue_serialization.h as to how to use it. - Detemplatized a bunch of epee/storages code. Most of it should have have been using templates at all (because it can only ever be called with one type!), and now it isn't. This broke some things that didn't properly compile because of missing headers or (in one case) a messed up circular dependency. - Significantly simplified a bunch of over-templatized serialization code. - All RPC serialization definitions is now out of core_rpc_server_commands_defs.h and into a single .cpp file (core_rpc_server_commands_defs.cpp). - core RPC no longer uses the disgusting BEGIN_URI_MAP2/MAP_URI_BLAH_BLAH macros. This was a terrible design that forced slamming tons of code into a common header that didn't need to be there. - epee::struct_init is gone. It was a horrible hack that instiated multiple templates just so the coder could be so lazy and write `some_type var;` instead of properly value initializing with `some_type var{};`. - Removed a bunch of useless crap from epee. In particular, forcing extra template instantiations all over the place in order to nest return objects inside JSON RPC values is no longer needed, as are a bunch of stuff related to the above de-macroization of the code. - get_all_service_nodes, get_service_nodes, and get_n_service_nodes are now combined into a single `get_service_nodes` (with deprecated aliases for the others), which eliminates a fair amount of duplication. The biggest obstacle here was getting the requested fields reference passed through: this is now done by a new ability to stash a context in the serialization object that can be retrieved by a sub-serialized type. LMQ-specifics: - The LokiMQ instance moves into `cryptonote::core` rather than being inside cryptonote_protocol. Currently the instance is used both for qnet and rpc calls (and so needs to be in a common place), but I also intend future PRs to use the batching code for job processing (replacing the current threaded job queue). - rpc/lmq_server.h handles the actual LMQ-request-to-core-RPC glue. Unlike http_server it isn't technically running the whole LMQ stack from here, but the parallel name with http_server seemed appropriate. - All RPC endpoints are supported by LMQ under the same names as defined generically, but prefixed with `rpc.` for public commands and `admin.` for restricted ones. - service node keys are now always available, even when not running in `--service-node` mode: this is because we want the x25519 key for being able to offer CURVE encryption for lmq RPC end-points, and because it doesn't hurt to have them available all the time. In the RPC layer this is now called "get_service_keys" (with "get_service_node_key" as an alias) since they aren't strictly only for service nodes. This also means code needs to check m_service_node, and not m_service_node_keys, to tell if it is running as a service node. (This is also easier to notice because m_service_node_keys got renamed to `m_service_keys`). - Added block and mempool monitoring LMQ RPC endpoints: `sub.block` and `sub.mempool` subscribes the connection for new block and new mempool TX notifications. The latter can notify on just blink txes, or all new mempool txes (but only new ones -- txes dumped from a block don't trigger it). The client gets pushed a [`notify.block`, `height`, `hash`] or [`notify.tx`, `txhash`, `blob`] message when something arrives. Minor details: - rpc::version_t is now a {major,minor} pair. Forcing everyone to pack and unpack a uint32_t was gross. - Changed some macros to constexprs (e.g. CORE_RPC_ERROR_CODE_...). (This immediately revealed a couple of bugs in the RPC code that was assigning CORE_RPC_ERROR_CODE_... to a string, and it worked because the macro allows implicit conversion to a char). - De-templatizing useless templates in epee (i.e. a bunch of templated types that were never invoked with different types) revealed a painful circular dependency between epee and non-epee code for tor_address and i2p_address. This crap is now handled in a suitably named `net/epee_network_address_hack.cpp` hack because it really isn't trivial to extricate this mess. - Removed `epee/include/serialization/serialize_base.h`. Amazingly the code somehow still all works perfectly with this previously vital header removed. - Removed bitrotted, unused epee "crypted_storage" and "gzipped_inmemstorage" code. - Replaced a bunch of epee::misc_utils::auto_scope_leave_caller with LOKI_DEFERs. The epee version involves quite a bit more instantiation and is ugly as sin. Also made the `loki::defer` class invokable for some edge cases that need calling before destruction in particular conditions. - Moved the systemd code around; it makes much more sense to do the systemd started notification as in daemon.cpp as late as possible rather than in core (when we can still have startup failures, e.g. if the RPC layer can't start). - Made the systemd short status string available in the get_info RPC (and no longer require building with systemd). - during startup, print (only) the x25519 when not in SN mode, and continue to print all three when in SN mode. - DRYed out some RPC implementation code (such as set_limit) - Made wallet_rpc stop using a raw m_wallet pointer
2020-04-28 01:25:43 +02:00
if (it == m_command_handlers.end())
throw invalid_command{cmd.front()};
std::any pre_result;
if (m_pre_handler)
pre_result = m_pre_handler(cmd.front());
bool result = it->second.first(std::vector<std::string>{cmd.begin()+1, cmd.end()});
if (m_post_handler)
m_post_handler(cmd.front(), result, std::move(pre_result));
return result;
2014-03-03 23:07:58 +01:00
}
bool process_command_and_log(const std::vector<std::string> &cmd)
{
try
{
return process_command(cmd);
}
catch (const invalid_command &e)
{
rdln::suspend_readline pause_readline;
std::cout << "Unknown command: " << e.what() << ". Try 'help' for available commands\n";
}
catch (const std::exception &e)
{
rdln::suspend_readline pause_readline;
std::cout << "Command errored: " << cmd.front() << ", " << e.what() << "\n";
}
return false;
}
2020-06-22 02:17:04 +02:00
bool process_command_and_log(const std::optional<std::string>& cmd)
2014-03-03 23:07:58 +01:00
{
if (!cmd)
return m_cancel_handler();
2014-03-03 23:07:58 +01:00
std::vector<std::string> cmd_v;
boost::split(cmd_v,*cmd,boost::is_any_of(" "), boost::token_compress_on);
return process_command_and_log(cmd_v);
2014-03-03 23:07:58 +01:00
}
void set_cancel_handler(const empty_callback& hndlr)
{
m_cancel_handler = hndlr;
}
private:
pre_handler_callback m_pre_handler;
post_handler_callback m_post_handler;
lookup m_command_handlers;
empty_callback m_cancel_handler;
};
2014-03-03 23:07:58 +01:00
/************************************************************************/
/* */
/************************************************************************/
class console_handlers_binder : public command_handler
{
typedef command_handler::callback console_command_handler;
typedef command_handler::lookup command_handlers_map;
daemon & daemonize overhaul This commit continues the complete replacement of the spaghetti code mess that was inside daemon/ and daemonize/ which started in #1138, and looked like a entry level Java programmer threw up inside the code base. This greatly simplifies it, removing a whole pile of useless abstraction layers that don't actually abstract anything, and results in considerably simpler code. (Many of the changes here were also carried out in #1138; this commit updates them with the merged result which amends some things from that PR and goes further in some places). In detail: - the `--detach` (and related `--pidfile`) options are gone. (--detach is still handled, but now just prints a fatal error). Detaching a process is an archaic unix mechanism that has no place on a modern system. If you *really* want to do it anyway, `nohup lokid &` will do the job. (The Windows service control code, which is probably seldom used, is kept because it seems potentially useful for Windows users). - Many of the `t_whatever` classes in daemon/* are just deleted (mostly done in #1138); each one was a bunch of junk code that wraps 3-4 lines but forces an extra layer (not even a generic abstraction, just a useless wrapper) for no good reason and made the daemon code painfully hard to understand and work with. - All of the remaining `t_whatever` classes in daemon/* are either renamed to `whatever` (because prefixing every class with `t_` is moronic). - Some stupid related code (e.g. epee's command handler returning an unsuitable "usage" string that has to be string modified into what we want) was replaced with more generic, useful code. - Replaced boost mutexes/cvs with std ones in epee command handler, and deleted some commented out code. - The `--public-node` option handling was terrible: it was being handled in main, but main doesn't know anything about options, so then it forced it through the spaghetti objects *beside* the pack of all options that got passed along. Moved it to a more sane location (core_rpc_server) and parse it out with some sanity. - Changed a bunch of std::bind's to lambdas because, at least for small lambdas (i.e. with only one-or-two pointers for captures) they will generally be more efficient as the values can be stored in std::function's without any memory allocations.
2020-04-02 22:38:52 +02:00
std::thread m_console_thread;
async_console_handler m_console_handler;
public:
~console_handlers_binder() {
try
{
stop_handling();
if (m_console_thread.joinable())
m_console_thread.join();
}
catch (const std::exception &e)
{ /*ignore*/
}
}
bool start_handling(std::function<std::string()> prompt, const std::string& usage_string = "", std::function<void()> exit_handler = NULL)
2014-03-03 23:07:58 +01:00
{
daemon & daemonize overhaul This commit continues the complete replacement of the spaghetti code mess that was inside daemon/ and daemonize/ which started in #1138, and looked like a entry level Java programmer threw up inside the code base. This greatly simplifies it, removing a whole pile of useless abstraction layers that don't actually abstract anything, and results in considerably simpler code. (Many of the changes here were also carried out in #1138; this commit updates them with the merged result which amends some things from that PR and goes further in some places). In detail: - the `--detach` (and related `--pidfile`) options are gone. (--detach is still handled, but now just prints a fatal error). Detaching a process is an archaic unix mechanism that has no place on a modern system. If you *really* want to do it anyway, `nohup lokid &` will do the job. (The Windows service control code, which is probably seldom used, is kept because it seems potentially useful for Windows users). - Many of the `t_whatever` classes in daemon/* are just deleted (mostly done in #1138); each one was a bunch of junk code that wraps 3-4 lines but forces an extra layer (not even a generic abstraction, just a useless wrapper) for no good reason and made the daemon code painfully hard to understand and work with. - All of the remaining `t_whatever` classes in daemon/* are either renamed to `whatever` (because prefixing every class with `t_` is moronic). - Some stupid related code (e.g. epee's command handler returning an unsuitable "usage" string that has to be string modified into what we want) was replaced with more generic, useful code. - Replaced boost mutexes/cvs with std ones in epee command handler, and deleted some commented out code. - The `--public-node` option handling was terrible: it was being handled in main, but main doesn't know anything about options, so then it forced it through the spaghetti objects *beside* the pack of all options that got passed along. Moved it to a more sane location (core_rpc_server) and parse it out with some sanity. - Changed a bunch of std::bind's to lambdas because, at least for small lambdas (i.e. with only one-or-two pointers for captures) they will generally be more efficient as the values can be stored in std::function's without any memory allocations.
2020-04-02 22:38:52 +02:00
m_console_thread = std::thread{std::bind(&console_handlers_binder::run_handling, this, prompt, usage_string, exit_handler)};
2014-03-03 23:07:58 +01:00
return true;
}
bool start_handling(const std::string &prompt, const std::string& usage_string = "", std::function<void()> exit_handler = NULL)
{
return start_handling([prompt](){ return prompt; }, usage_string, exit_handler);
}
2014-03-03 23:07:58 +01:00
2014-03-20 12:46:11 +01:00
void stop_handling()
2014-03-03 23:07:58 +01:00
{
2014-03-20 12:46:11 +01:00
m_console_handler.stop();
2014-03-03 23:07:58 +01:00
}
bool run_handling(std::function<std::string()> prompt, const std::string& usage_string, std::function<void()> exit_handler = NULL)
2014-03-03 23:07:58 +01:00
{
return m_console_handler.run([this](const auto& arg) { return process_command_and_log(arg); }, prompt, usage_string, exit_handler);
2014-03-03 23:07:58 +01:00
}
void print_prompt()
{
m_console_handler.print_prompt();
}
void cancel_input()
{
m_console_handler.cancel();
}
2014-03-03 23:07:58 +01:00
};
}