2014-07-25 18:29:08 +02:00
|
|
|
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
|
2014-03-03 23:07:58 +01:00
|
|
|
// All rights reserved.
|
2014-07-25 18:29:08 +02:00
|
|
|
//
|
|
|
|
// 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
|
|
|
|
|
2015-01-29 23:10:53 +01:00
|
|
|
#include "misc_log_ex.h"
|
2017-11-25 23:25:05 +01:00
|
|
|
#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>
|
2015-01-29 23:10:53 +01:00
|
|
|
#include <iostream>
|
2020-06-22 03:04:09 +02:00
|
|
|
#include <any>
|
|
|
|
#include <unordered_map>
|
2016-01-21 19:18:26 +01:00
|
|
|
#ifdef __OpenBSD__
|
|
|
|
#include <stdio.h>
|
|
|
|
#endif
|
2017-11-25 23:25:05 +01:00
|
|
|
#include <boost/algorithm/string/classification.hpp>
|
|
|
|
#include <boost/algorithm/string/split.hpp>
|
2014-03-20 12:46:11 +01:00
|
|
|
|
2017-05-30 00:39:49 +02:00
|
|
|
#ifdef HAVE_READLINE
|
|
|
|
#include "readline_buffer.h"
|
|
|
|
#endif
|
|
|
|
|
2019-05-06 10:44:50 +02:00
|
|
|
#undef MONERO_DEFAULT_LOG_CATEGORY
|
|
|
|
#define MONERO_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)
|
|
|
|
{
|
2017-05-30 00:39:49 +02:00
|
|
|
#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()
|
|
|
|
{
|
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
|
|
|
|
2017-05-30 00:39:49 +02: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
|
|
|
|
2015-05-30 20:24:15 +02: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
|
|
|
|
2019-05-06 10:44:50 +02:00
|
|
|
if (!eos() && m_read_status != state_cancelled)
|
2015-05-30 20:24:15 +02:00
|
|
|
m_read_status = state_init;
|
2014-03-20 12:46:11 +01:00
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2015-05-30 20:24:15 +02:00
|
|
|
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();
|
2017-05-30 00:39:49 +02:00
|
|
|
#ifdef HAVE_READLINE
|
|
|
|
m_readline_buffer.stop();
|
|
|
|
#endif
|
2014-03-20 12:46:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-06 10:44:50 +02:00
|
|
|
void cancel()
|
|
|
|
{
|
2020-05-20 10:14:48 +02:00
|
|
|
std::unique_lock<std::mutex> lock(m_response_mutex);
|
2019-05-06 10:44:50 +02:00
|
|
|
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
|
|
|
{
|
2019-05-06 10:44:50 +02: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;
|
|
|
|
}
|
2016-11-17 23:08:32 +01:00
|
|
|
#else
|
|
|
|
while (m_run.load(std::memory_order_relaxed))
|
|
|
|
{
|
2019-05-06 10:44:50 +02:00
|
|
|
if (m_read_status == state_cancelled)
|
|
|
|
return false;
|
|
|
|
|
2016-11-17 23:08:32 +01:00
|
|
|
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;
|
2017-08-21 13:55:06 +02:00
|
|
|
#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))
|
|
|
|
{
|
2017-05-30 00:39:49 +02:00
|
|
|
#ifdef HAVE_READLINE
|
2017-08-21 13:55:06 +02:00
|
|
|
switch (m_readline_buffer.get_line(line))
|
|
|
|
{
|
|
|
|
case rdln::empty: goto eof;
|
|
|
|
case rdln::partial: goto reread;
|
|
|
|
case rdln::full: break;
|
|
|
|
}
|
2017-05-30 00:39:49 +02:00
|
|
|
#else
|
2019-05-06 10:44:50 +02:00
|
|
|
if (m_read_status != state_cancelled)
|
|
|
|
std::getline(std::cin, line);
|
2017-05-30 00:39:49 +02:00
|
|
|
#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;
|
|
|
|
}
|
2015-05-30 20:24:15 +02:00
|
|
|
if (std::cin.eof()) {
|
2017-08-21 13:55:06 +02:00
|
|
|
#ifdef HAVE_READLINE
|
|
|
|
eof:
|
|
|
|
#endif
|
2015-05-30 20:24:15 +02:00
|
|
|
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,
|
2015-05-30 20:24:15 +02:00
|
|
|
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;
|
2017-05-30 00:39:49 +02:00
|
|
|
#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
|
|
|
|
2020-06-03 06:45:51 +02:00
|
|
|
template<class t_server, class chain_handler>
|
2020-06-22 02:31:21 +02:00
|
|
|
bool run(t_server* psrv, chain_handler ch_handler, std::function<std::string()> prompt, const std::string& usage = "")
|
2020-06-03 06:45:51 +02:00
|
|
|
{
|
|
|
|
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>
|
2020-06-22 02:31:21 +02:00
|
|
|
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()
|
|
|
|
{
|
2014-06-13 06:01:26 +02:00
|
|
|
m_running = false;
|
2014-03-20 12:46:11 +01:00
|
|
|
m_stdin_reader.stop();
|
|
|
|
}
|
|
|
|
|
2019-05-06 10:44:50 +02:00
|
|
|
void cancel()
|
|
|
|
{
|
|
|
|
m_cancel = true;
|
|
|
|
m_stdin_reader.cancel();
|
|
|
|
}
|
|
|
|
|
2015-11-28 13:38:58 +01:00
|
|
|
void print_prompt()
|
|
|
|
{
|
2017-08-02 15:44:42 +02:00
|
|
|
std::string prompt = m_prompt();
|
|
|
|
if (!prompt.empty())
|
2015-11-28 13:38:58 +01:00
|
|
|
{
|
2017-05-30 00:39:49 +02:00
|
|
|
#ifdef HAVE_READLINE
|
2017-08-02 15:44:42 +02:00
|
|
|
std::string color_prompt = "\001\033[1;33m\002" + prompt;
|
|
|
|
if (' ' != prompt.back())
|
2017-06-20 15:22:55 +02:00
|
|
|
color_prompt += " ";
|
|
|
|
color_prompt += "\001\033[0m\002";
|
|
|
|
m_stdin_reader.get_readline_buffer().set_prompt(color_prompt);
|
2017-05-30 00:39:49 +02:00
|
|
|
#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);
|
2017-08-02 15:44:42 +02:00
|
|
|
std::cout << prompt;
|
|
|
|
if (' ' != prompt.back())
|
2015-11-28 13:38:58 +01:00
|
|
|
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();
|
2015-11-28 13:38:58 +01:00
|
|
|
std::cout.flush();
|
2017-05-30 00:39:49 +02:00
|
|
|
#endif
|
2015-11-28 13:38:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-20 12:46:11 +01:00
|
|
|
private:
|
2015-06-03 23:42:30 +02:00
|
|
|
template<typename t_cmd_handler>
|
2020-06-22 02:31:21 +02:00
|
|
|
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;
|
2015-11-28 13:38:58 +01:00
|
|
|
m_prompt = prompt;
|
2014-03-20 12:46:11 +01:00
|
|
|
while(continue_handle)
|
2014-03-03 23:07:58 +01:00
|
|
|
{
|
2015-12-06 23:03:53 +01:00
|
|
|
try
|
2014-06-13 06:01:26 +02:00
|
|
|
{
|
2015-12-06 23:03:53 +01:00
|
|
|
if (!m_running)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
print_prompt();
|
2014-03-20 12:46:11 +01:00
|
|
|
|
2015-12-06 23:03:53 +01:00
|
|
|
std::string command;
|
|
|
|
bool get_line_ret = m_stdin_reader.get_line(command);
|
2018-10-20 11:12:55 +02:00
|
|
|
if (!m_running)
|
|
|
|
break;
|
|
|
|
if (m_stdin_reader.eos())
|
2015-12-06 23:03:53 +01:00
|
|
|
{
|
2018-10-20 11:12:55 +02:00
|
|
|
MGINFO("EOF on stdin, exiting");
|
2019-03-13 17:51:09 +01:00
|
|
|
std::cout << std::endl;
|
2015-12-06 23:03:53 +01:00
|
|
|
break;
|
|
|
|
}
|
2019-05-06 10:44:50 +02:00
|
|
|
|
|
|
|
if (m_cancel)
|
|
|
|
{
|
|
|
|
MDEBUG("Input cancelled");
|
2020-06-22 02:17:04 +02:00
|
|
|
cmd_handler(std::nullopt);
|
2019-05-06 10:44:50 +02:00
|
|
|
m_cancel = false;
|
|
|
|
continue;
|
|
|
|
}
|
2015-12-06 23:03:53 +01:00
|
|
|
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.");
|
2015-12-06 23:03:53 +01:00
|
|
|
}
|
2019-05-06 10:44:50 +02:00
|
|
|
|
2015-12-06 23:03:53 +01:00
|
|
|
string_tools::trim(command);
|
2014-03-20 12:46:11 +01:00
|
|
|
|
2015-12-06 23:03:53 +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
|
|
|
|
{
|
2020-05-20 04:27:22 +02:00
|
|
|
cmd_handler(command);
|
2015-12-06 23:03:53 +01:00
|
|
|
}
|
2015-03-27 13:01:30 +01:00
|
|
|
}
|
2015-12-06 23:03:53 +01:00
|
|
|
catch (const std::exception &ex)
|
2014-03-20 12:46:11 +01:00
|
|
|
{
|
2015-12-06 23:03:53 +01:00
|
|
|
LOG_ERROR("Exception at [console_handler], what=" << ex.what());
|
2014-03-03 23:07:58 +01:00
|
|
|
}
|
|
|
|
}
|
2015-07-18 11:53:20 +02: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;
|
2015-01-29 23:10:53 +01:00
|
|
|
std::atomic<bool> m_running = {true};
|
2019-05-06 10:44:50 +02:00
|
|
|
std::atomic<bool> m_cancel = {false};
|
2020-06-22 02:31:21 +02:00
|
|
|
std::function<std::string()> m_prompt;
|
2014-03-20 12:46:11 +01:00
|
|
|
};
|
2014-03-03 23:07:58 +01:00
|
|
|
|
2015-01-29 23:10:53 +01:00
|
|
|
class command_handler {
|
2014-03-20 12:46:11 +01:00
|
|
|
public:
|
2020-06-22 02:31:21 +02:00
|
|
|
using callback = std::function<bool(const std::vector<std::string> &)>;
|
|
|
|
using empty_callback = std::function<bool()>;
|
|
|
|
using lookup = std::unordered_map<std::string, std::pair<callback, std::pair<std::string, std::string>>>;
|
2015-01-29 23:10:53 +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
|
|
|
/// 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
|
|
|
}
|
2015-01-29 23:10:53 +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;
|
|
|
|
}
|
|
|
|
|
2020-06-22 03:04:09 +02:00
|
|
|
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
|
|
|
{
|
2015-01-29 23:10:53 +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)};
|
2017-07-07 21:40:32 +02:00
|
|
|
#ifdef HAVE_READLINE
|
|
|
|
rdln::readline_buffer::add_completion(cmd);
|
|
|
|
#endif
|
2014-03-03 23:07:58 +01:00
|
|
|
}
|
2015-01-29 23:10:53 +01:00
|
|
|
|
2020-05-20 04:27:22 +02: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).
|
2020-05-20 04:27:22 +02:00
|
|
|
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())
|
2020-05-20 04:27:22 +02:00
|
|
|
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())
|
2020-05-20 04:27:22 +02:00
|
|
|
throw invalid_command{cmd.front()};
|
2020-06-22 03:04:09 +02:00
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2020-05-20 04:27:22 +02:00
|
|
|
bool process_command_and_log(const std::vector<std::string> &cmd)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
return process_command(cmd);
|
|
|
|
}
|
|
|
|
catch (const invalid_command &e)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_READLINE
|
|
|
|
rdln::suspend_readline pause_readline;
|
|
|
|
#endif
|
|
|
|
std::cout << "Unknown command: " << e.what() << ". Try 'help' for available commands\n";
|
|
|
|
}
|
|
|
|
catch (const std::exception &e)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_READLINE
|
|
|
|
rdln::suspend_readline pause_readline;
|
|
|
|
#endif
|
|
|
|
std::cout << "Command errored: " << cmd.front() << ", " << e.what();
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
{
|
2020-06-03 06:45:51 +02:00
|
|
|
if (!cmd)
|
|
|
|
return m_cancel_handler();
|
2014-03-03 23:07:58 +01:00
|
|
|
std::vector<std::string> cmd_v;
|
2020-06-03 06:45:51 +02:00
|
|
|
boost::split(cmd_v,*cmd,boost::is_any_of(" "), boost::token_compress_on);
|
2020-05-20 04:27:22 +02:00
|
|
|
return process_command_and_log(cmd_v);
|
2014-03-03 23:07:58 +01:00
|
|
|
}
|
2020-05-20 04:27:22 +02:00
|
|
|
|
2020-06-03 06:45:51 +02:00
|
|
|
void set_cancel_handler(const empty_callback& hndlr)
|
|
|
|
{
|
|
|
|
m_cancel_handler = hndlr;
|
|
|
|
}
|
|
|
|
|
2015-01-29 23:10:53 +01:00
|
|
|
private:
|
2020-06-22 03:04:09 +02:00
|
|
|
pre_handler_callback m_pre_handler;
|
|
|
|
post_handler_callback m_post_handler;
|
2015-01-29 23:10:53 +01:00
|
|
|
lookup m_command_handlers;
|
2020-06-03 06:45:51 +02:00
|
|
|
empty_callback m_cancel_handler;
|
2015-01-29 23:10:53 +01:00
|
|
|
};
|
2014-03-03 23:07:58 +01:00
|
|
|
|
2015-01-29 23:10:53 +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;
|
2015-01-29 23:10:53 +01:00
|
|
|
async_console_handler m_console_handler;
|
|
|
|
public:
|
2019-11-12 17:05:17 +01:00
|
|
|
~console_handlers_binder() {
|
2020-02-12 14:57:04 +01:00
|
|
|
try
|
2019-11-12 17:05:17 +01:00
|
|
|
{
|
2020-02-12 14:57:04 +01:00
|
|
|
stop_handling();
|
2020-05-28 07:02:40 +02:00
|
|
|
if (m_console_thread.joinable())
|
|
|
|
m_console_thread.join();
|
|
|
|
}
|
|
|
|
catch (const std::exception &e)
|
|
|
|
{ /*ignore*/
|
2019-11-12 17:05:17 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-22 02:31:21 +02:00
|
|
|
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;
|
|
|
|
}
|
2020-06-22 02:31:21 +02:00
|
|
|
bool start_handling(const std::string &prompt, const std::string& usage_string = "", std::function<void()> exit_handler = NULL)
|
2017-08-02 15:44:42 +02:00
|
|
|
{
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2020-06-22 02:31:21 +02: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
|
|
|
{
|
2020-05-20 04:27:22 +02: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
|
|
|
}
|
2015-11-28 13:38:58 +01:00
|
|
|
|
|
|
|
void print_prompt()
|
|
|
|
{
|
|
|
|
m_console_handler.print_prompt();
|
|
|
|
}
|
2019-05-06 10:44:50 +02:00
|
|
|
|
|
|
|
void cancel_input()
|
|
|
|
{
|
|
|
|
m_console_handler.cancel();
|
|
|
|
}
|
2014-03-03 23:07:58 +01:00
|
|
|
};
|
|
|
|
}
|