mirror of
https://github.com/oxen-io/oxen-core.git
synced 2023-12-14 02:22:56 +01:00
wallet_rpc: Simplify daemonizer, remove t_handler/t_executor
The daemonizer requires you to fill out an "interface" to use it. This imposes a design constraint on end users whens starting up applications and led to a initialization circus with a t_executor starting up a t_daemon that creates an instance of our application. Instead design it so that execution flow is controlled by the user and not the interface by returning the run_type that the user requested (run as a service, forked, interactive or non-interactive) and launch accordingly at the call site, and not indirected through 2 classes of OOP cruft. There still remains 1 wart with the Windows daemonizer requiring templatization on the application so that Windows can callback at a their deferred discretion and startup and shutdown the application accordingly.
This commit is contained in:
parent
ee44c01c69
commit
2909ad886a
8 changed files with 170 additions and 171 deletions
|
@ -57,10 +57,22 @@ namespace daemonizer
|
|||
, T_executor && executor // universal ref
|
||||
, boost::program_options::variables_map const & vm
|
||||
);
|
||||
|
||||
|
||||
enum struct run_type
|
||||
{
|
||||
non_interactive,
|
||||
interactive,
|
||||
service,
|
||||
terminate,
|
||||
terminate_with_error,
|
||||
};
|
||||
template <typename Application>
|
||||
run_type setup_run_environment(char const *name, int argc, char const *argv[], boost::program_options::variables_map const &vm);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
# include "daemonizer/windows_daemonizer.inl"
|
||||
#include "daemonizer/windows_daemonizer.inl"
|
||||
#else
|
||||
# include "daemonizer/posix_daemonizer.inl"
|
||||
#include "daemonizer/posix_daemonizer.inl"
|
||||
#endif
|
||||
|
|
|
@ -92,8 +92,7 @@ namespace daemonizer
|
|||
pidfile = command_line::get_arg(vm, arg_pidfile);
|
||||
}
|
||||
posix::fork(pidfile);
|
||||
auto daemon = executor.create_daemon(vm);
|
||||
return daemon.run();
|
||||
return executor.run_non_interactive(vm);
|
||||
}
|
||||
else if (command_line::has_arg(vm, arg_non_interactive))
|
||||
{
|
||||
|
@ -105,4 +104,25 @@ namespace daemonizer
|
|||
return executor.run_interactive(vm);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Application>
|
||||
inline run_type setup_run_environment(char const *name, int argc, char const *argv[], boost::program_options::variables_map const &vm)
|
||||
{
|
||||
(void)name; (void)argc; (void)argv;
|
||||
if (command_line::has_arg(vm, arg_detach))
|
||||
{
|
||||
tools::success_msg_writer() << "Forking to background...";
|
||||
std::string pidfile;
|
||||
if (command_line::has_arg(vm, arg_pidfile))
|
||||
{
|
||||
pidfile = command_line::get_arg(vm, arg_pidfile);
|
||||
}
|
||||
posix::fork(pidfile);
|
||||
return run_type::non_interactive;
|
||||
}
|
||||
else if (command_line::has_arg(vm, arg_non_interactive))
|
||||
return run_type::non_interactive;
|
||||
|
||||
return run_type::interactive;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,9 +142,15 @@ namespace daemonizer
|
|||
{
|
||||
std::string arguments = get_argument_string(argc, argv);
|
||||
|
||||
#if 0
|
||||
if (command_line::has_arg(vm, arg_is_service))
|
||||
{
|
||||
// TODO - Set the service status here for return codes
|
||||
static t_service_runner<T_handler> runner = {};
|
||||
runner.name = executor.name();
|
||||
runner.handler = executor.create_daemon();
|
||||
runner.run_();
|
||||
|
||||
windows::t_service_runner<typename T_executor::t_daemon>::run(
|
||||
executor.name()
|
||||
, executor.create_daemon(vm)
|
||||
|
@ -188,7 +194,59 @@ namespace daemonizer
|
|||
else
|
||||
return executor.run_interactive(vm);
|
||||
}
|
||||
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Application>
|
||||
inline run_type setup_run_environment(char const *name, int argc, char const *argv[], boost::program_options::variables_map const &vm)
|
||||
{
|
||||
std::string arguments = get_argument_string(argc, argv);
|
||||
|
||||
if (command_line::has_arg(vm, arg_is_service))
|
||||
{
|
||||
Application app(&vm);
|
||||
windows::service_runner<Application> runner(name, &app);
|
||||
runner.run();
|
||||
return run_type::terminate;
|
||||
}
|
||||
else if (command_line::has_arg(vm, arg_install_service))
|
||||
{
|
||||
if (windows::ensure_admin(arguments))
|
||||
{
|
||||
arguments += " --run-as-service";
|
||||
bool result = windows::install_service(name, arguments);
|
||||
return result ? run_type::terminate : run_type::terminate_with_error;
|
||||
}
|
||||
}
|
||||
else if (command_line::has_arg(vm, arg_uninstall_service))
|
||||
{
|
||||
if (windows::ensure_admin(arguments))
|
||||
{
|
||||
bool result = windows::uninstall_service(name);
|
||||
return result ? run_type::terminate : run_type::terminate_with_error;
|
||||
}
|
||||
}
|
||||
else if (command_line::has_arg(vm, arg_start_service))
|
||||
{
|
||||
if (windows::ensure_admin(arguments))
|
||||
{
|
||||
bool result = windows::start_service(name);
|
||||
return result ? run_type::terminate : run_type::terminate_with_error;
|
||||
}
|
||||
}
|
||||
else if (command_line::has_arg(vm, arg_stop_service))
|
||||
{
|
||||
if (windows::ensure_admin(arguments))
|
||||
{
|
||||
bool result = windows::stop_service(name);
|
||||
return result ? run_type::terminate : run_type::terminate_with_error;
|
||||
}
|
||||
}
|
||||
|
||||
if (command_line::has_arg(vm, arg_non_interactive))
|
||||
return run_type::non_interactive;
|
||||
else
|
||||
return run_type::interactive;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -166,10 +166,7 @@ bool ensure_admin(
|
|||
}
|
||||
}
|
||||
|
||||
bool install_service(
|
||||
std::string const & service_name
|
||||
, std::string const & arguments
|
||||
)
|
||||
bool install_service(char const *service_name, std::string const &arguments)
|
||||
{
|
||||
std::string command = epee::string_tools::get_current_module_path();
|
||||
std::string full_command = command + arguments;
|
||||
|
@ -191,8 +188,8 @@ bool install_service(
|
|||
service_handle p_service{
|
||||
CreateService(
|
||||
p_manager.get()
|
||||
, service_name.c_str()
|
||||
, service_name.c_str()
|
||||
, service_name
|
||||
, service_name
|
||||
, 0
|
||||
//, GENERIC_EXECUTE | GENERIC_READ
|
||||
, SERVICE_WIN32_OWN_PROCESS
|
||||
|
@ -221,9 +218,7 @@ bool install_service(
|
|||
return true;
|
||||
}
|
||||
|
||||
bool start_service(
|
||||
std::string const & service_name
|
||||
)
|
||||
bool start_service(char const *service_name)
|
||||
{
|
||||
tools::msg_writer() << "Starting service";
|
||||
|
||||
|
@ -247,7 +242,7 @@ bool start_service(
|
|||
service_handle p_service{
|
||||
OpenService(
|
||||
p_manager.get()
|
||||
, service_name.c_str()
|
||||
, service_name
|
||||
//, SERVICE_START | SERVICE_QUERY_STATUS
|
||||
, SERVICE_START
|
||||
)
|
||||
|
@ -276,9 +271,7 @@ bool start_service(
|
|||
return true;
|
||||
}
|
||||
|
||||
bool stop_service(
|
||||
std::string const & service_name
|
||||
)
|
||||
bool stop_service(char const *service_name)
|
||||
{
|
||||
tools::msg_writer() << "Stopping service";
|
||||
|
||||
|
@ -299,7 +292,7 @@ bool stop_service(
|
|||
service_handle p_service{
|
||||
OpenService(
|
||||
p_manager.get()
|
||||
, service_name.c_str()
|
||||
, service_name
|
||||
, SERVICE_STOP | SERVICE_QUERY_STATUS
|
||||
)
|
||||
, &::CloseServiceHandle
|
||||
|
@ -324,9 +317,7 @@ bool stop_service(
|
|||
return true;
|
||||
}
|
||||
|
||||
bool uninstall_service(
|
||||
std::string const & service_name
|
||||
)
|
||||
bool uninstall_service(char const *service_name)
|
||||
{
|
||||
service_handle p_manager{
|
||||
OpenSCManager(
|
||||
|
@ -345,7 +336,7 @@ bool uninstall_service(
|
|||
service_handle p_service{
|
||||
OpenService(
|
||||
p_manager.get()
|
||||
, service_name.c_str()
|
||||
, service_name
|
||||
, SERVICE_QUERY_STATUS | DELETE
|
||||
)
|
||||
, &::CloseServiceHandle
|
||||
|
|
|
@ -40,25 +40,14 @@ namespace windows
|
|||
{
|
||||
bool check_admin(bool & result);
|
||||
|
||||
bool ensure_admin(
|
||||
std::string const & arguments
|
||||
);
|
||||
bool ensure_admin(std::string const &arguments);
|
||||
|
||||
bool install_service(
|
||||
std::string const & service_name
|
||||
, std::string const & arguments
|
||||
);
|
||||
bool install_service(char const *service_name, std::string const &arguments);
|
||||
|
||||
bool uninstall_service(
|
||||
std::string const & service_name
|
||||
);
|
||||
bool uninstall_service(char const *service_name);
|
||||
|
||||
bool start_service(
|
||||
std::string const & service_name
|
||||
);
|
||||
bool start_service(char const *service_name);
|
||||
|
||||
bool stop_service(
|
||||
std::string const & service_name
|
||||
);
|
||||
bool stop_service(char const *service_name);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -40,35 +40,28 @@
|
|||
#include <windows.h>
|
||||
|
||||
namespace windows {
|
||||
namespace
|
||||
{
|
||||
std::vector<char> vecstring(std::string const & str)
|
||||
{
|
||||
std::vector<char> result{str.begin(), str.end()};
|
||||
result.push_back('\0');
|
||||
return result;
|
||||
}
|
||||
}
|
||||
static void *runner_instance; // For C-style callbacks to call into C++ classes
|
||||
|
||||
template <typename T_handler>
|
||||
class t_service_runner final
|
||||
template <typename Application>
|
||||
class service_runner final
|
||||
{
|
||||
private:
|
||||
SERVICE_STATUS_HANDLE m_status_handle{nullptr};
|
||||
SERVICE_STATUS m_status{};
|
||||
boost::mutex m_lock{};
|
||||
std::string m_name;
|
||||
T_handler m_handler;
|
||||
Application *app;
|
||||
|
||||
static std::unique_ptr<t_service_runner<T_handler>> sp_instance;
|
||||
public:
|
||||
t_service_runner(
|
||||
service_runner(
|
||||
std::string name
|
||||
, T_handler handler
|
||||
, Application *app
|
||||
)
|
||||
: m_name{std::move(name)}
|
||||
, m_handler{std::move(handler)}
|
||||
, app{app}
|
||||
{
|
||||
windows::runner_instance = this;
|
||||
|
||||
m_status.dwServiceType = SERVICE_WIN32;
|
||||
m_status.dwCurrentState = SERVICE_STOPPED;
|
||||
m_status.dwControlsAccepted = 0;
|
||||
|
@ -77,43 +70,17 @@ namespace windows {
|
|||
m_status.dwCheckPoint = 0;
|
||||
m_status.dwWaitHint = 0;
|
||||
}
|
||||
service_runner &operator=(service_runner &&other) = delete;
|
||||
|
||||
t_service_runner & operator=(t_service_runner && other)
|
||||
void run()
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
m_status_handle = std::move(other.m_status_handle);
|
||||
m_status = std::move(other.m_status);
|
||||
m_name = std::move(other.m_name);
|
||||
m_handler = std::move(other.m_handler);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
static void run(
|
||||
std::string name
|
||||
, T_handler handler
|
||||
)
|
||||
{
|
||||
sp_instance.reset(new t_service_runner<T_handler>{
|
||||
std::move(name)
|
||||
, std::move(handler)
|
||||
});
|
||||
|
||||
sp_instance->run_();
|
||||
}
|
||||
|
||||
private:
|
||||
void run_()
|
||||
{
|
||||
SERVICE_TABLE_ENTRY table[] =
|
||||
{
|
||||
{ vecstring(m_name).data(), &service_main }
|
||||
, { 0, 0 }
|
||||
};
|
||||
std::vector<char> name{m_name.begin(), m_name.end()};
|
||||
name.push_back('\0');
|
||||
SERVICE_TABLE_ENTRY const table[] = {{name.data(), &service_main}, {0, 0}};
|
||||
|
||||
StartServiceCtrlDispatcher(table);
|
||||
}
|
||||
private:
|
||||
|
||||
void report_status(DWORD status)
|
||||
{
|
||||
|
@ -131,7 +98,7 @@ namespace windows {
|
|||
|
||||
static void WINAPI service_main(DWORD argc, LPSTR * argv)
|
||||
{
|
||||
sp_instance->service_main_(argc, argv);
|
||||
((service_runner *)windows::runner_instance)->service_main_(argc, argv);
|
||||
}
|
||||
|
||||
void service_main_(DWORD argc, LPSTR * argv)
|
||||
|
@ -143,17 +110,17 @@ namespace windows {
|
|||
|
||||
report_status(SERVICE_RUNNING);
|
||||
|
||||
m_handler.run();
|
||||
app->run();
|
||||
|
||||
on_state_change_request_(SERVICE_CONTROL_STOP);
|
||||
|
||||
// Ensure that the service is uninstalled
|
||||
uninstall_service(m_name);
|
||||
uninstall_service(m_name.c_str());
|
||||
}
|
||||
|
||||
static void WINAPI on_state_change_request(DWORD control_code)
|
||||
{
|
||||
sp_instance->on_state_change_request_(control_code);
|
||||
((service_runner *)windows::runner_instance)->on_state_change_request_(control_code);
|
||||
}
|
||||
|
||||
void on_state_change_request_(DWORD control_code)
|
||||
|
@ -165,7 +132,7 @@ namespace windows {
|
|||
case SERVICE_CONTROL_SHUTDOWN:
|
||||
case SERVICE_CONTROL_STOP:
|
||||
report_status(SERVICE_STOP_PENDING);
|
||||
m_handler.stop();
|
||||
app->stop();
|
||||
report_status(SERVICE_STOPPED);
|
||||
break;
|
||||
case SERVICE_CONTROL_PAUSE:
|
||||
|
@ -177,9 +144,6 @@ namespace windows {
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T_handler>
|
||||
std::unique_ptr<t_service_runner<T_handler>> t_service_runner<T_handler>::sp_instance;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -91,7 +91,12 @@ namespace tools
|
|||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
wallet_rpc_server::wallet_rpc_server():m_wallet(NULL), rpc_login_file(), m_stop(false), m_restricted(false), m_vm(NULL)
|
||||
wallet_rpc_server::wallet_rpc_server(boost::program_options::variables_map const *vm)
|
||||
: m_wallet(NULL)
|
||||
, rpc_login_file()
|
||||
, m_stop(false)
|
||||
, m_restricted(false)
|
||||
, m_vm(vm)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -106,7 +111,7 @@ namespace tools
|
|||
m_wallet = cr;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::run()
|
||||
bool wallet_rpc_server::run_server_threads()
|
||||
{
|
||||
m_stop = false;
|
||||
m_net_server.add_idle_handler([this](){
|
||||
|
@ -168,6 +173,7 @@ namespace tools
|
|||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
void wallet_rpc_server::stop()
|
||||
{
|
||||
send_stop_signal();
|
||||
if (m_wallet)
|
||||
{
|
||||
m_wallet->store();
|
||||
|
@ -176,14 +182,12 @@ namespace tools
|
|||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::init(const boost::program_options::variables_map *vm)
|
||||
bool wallet_rpc_server::init()
|
||||
{
|
||||
auto rpc_config = cryptonote::rpc_args::process(*vm);
|
||||
auto rpc_config = cryptonote::rpc_args::process(*m_vm);
|
||||
if (!rpc_config)
|
||||
return false;
|
||||
|
||||
m_vm = vm;
|
||||
|
||||
boost::optional<epee::net_utils::http::login> http_login{};
|
||||
std::string bind_port = command_line::get_arg(*m_vm, arg_rpc_bind_port);
|
||||
const bool disable_auth = command_line::get_arg(*m_vm, arg_disable_rpc_login);
|
||||
|
@ -4546,29 +4550,14 @@ namespace tools
|
|||
res.value = value.to_readable_value(m_wallet->nettype(), type);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class t_daemon
|
||||
{
|
||||
private:
|
||||
const boost::program_options::variables_map& vm;
|
||||
|
||||
std::unique_ptr<tools::wallet_rpc_server> wrpc;
|
||||
|
||||
public:
|
||||
t_daemon(boost::program_options::variables_map const & _vm)
|
||||
: vm(_vm)
|
||||
, wrpc(new tools::wallet_rpc_server)
|
||||
{
|
||||
}
|
||||
|
||||
bool run()
|
||||
bool wallet_rpc_server::run()
|
||||
{
|
||||
std::unique_ptr<tools::wallet2> wal;
|
||||
try
|
||||
{
|
||||
const bool testnet = tools::wallet2::has_testnet_option(vm);
|
||||
const bool stagenet = tools::wallet2::has_stagenet_option(vm);
|
||||
const bool testnet = tools::wallet2::has_testnet_option(*m_vm);
|
||||
const bool stagenet = tools::wallet2::has_stagenet_option(*m_vm);
|
||||
if (testnet && stagenet)
|
||||
{
|
||||
MERROR(tools::wallet_rpc_server::tr("Can't specify more than one of --testnet and --stagenet"));
|
||||
|
@ -4578,10 +4567,10 @@ public:
|
|||
const auto arg_wallet_file = wallet_args::arg_wallet_file();
|
||||
const auto arg_from_json = wallet_args::arg_generate_from_json();
|
||||
|
||||
const auto wallet_file = command_line::get_arg(vm, arg_wallet_file);
|
||||
const auto from_json = command_line::get_arg(vm, arg_from_json);
|
||||
const auto wallet_dir = command_line::get_arg(vm, arg_wallet_dir);
|
||||
const auto prompt_for_password = command_line::get_arg(vm, arg_prompt_for_password);
|
||||
const auto wallet_file = command_line::get_arg(*m_vm, arg_wallet_file);
|
||||
const auto from_json = command_line::get_arg(*m_vm, arg_from_json);
|
||||
const auto wallet_dir = command_line::get_arg(*m_vm, arg_wallet_dir);
|
||||
const auto prompt_for_password = command_line::get_arg(*m_vm, arg_prompt_for_password);
|
||||
const auto password_prompt = prompt_for_password ? password_prompter : nullptr;
|
||||
|
||||
if(!wallet_file.empty() && !from_json.empty())
|
||||
|
@ -4605,13 +4594,13 @@ public:
|
|||
LOG_PRINT_L0(tools::wallet_rpc_server::tr("Loading wallet..."));
|
||||
if(!wallet_file.empty())
|
||||
{
|
||||
wal = tools::wallet2::make_from_file(vm, true, wallet_file, password_prompt).first;
|
||||
wal = tools::wallet2::make_from_file(*m_vm, true, wallet_file, password_prompt).first;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
auto rc = tools::wallet2::make_from_json(vm, true, from_json, password_prompt);
|
||||
auto rc = tools::wallet2::make_from_json(*m_vm, true, from_json, password_prompt);
|
||||
wal = std::move(rc.first);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
|
@ -4648,17 +4637,17 @@ public:
|
|||
LOG_ERROR(tools::wallet_rpc_server::tr("Wallet initialization failed: ") << e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
just_dir:
|
||||
if (wal) wrpc->set_wallet(wal.release());
|
||||
bool r = wrpc->init(&vm);
|
||||
if (wal) set_wallet(wal.release());
|
||||
bool r = init();
|
||||
CHECK_AND_ASSERT_MES(r, false, tools::wallet_rpc_server::tr("Failed to initialize wallet RPC server"));
|
||||
tools::signal_handler::install([this](int) {
|
||||
wrpc->send_stop_signal();
|
||||
});
|
||||
tools::signal_handler::install([this](int) { send_stop_signal(); });
|
||||
|
||||
LOG_PRINT_L0(tools::wallet_rpc_server::tr("Starting wallet RPC server"));
|
||||
try
|
||||
{
|
||||
wrpc->run();
|
||||
run_server_threads();
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
|
@ -4669,7 +4658,7 @@ public:
|
|||
try
|
||||
{
|
||||
LOG_PRINT_L0(tools::wallet_rpc_server::tr("Saving wallet..."));
|
||||
wrpc->stop();
|
||||
stop();
|
||||
LOG_PRINT_L0(tools::wallet_rpc_server::tr("Successfully saved"));
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
|
@ -4679,44 +4668,10 @@ public:
|
|||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
wrpc->send_stop_signal();
|
||||
}
|
||||
};
|
||||
|
||||
class t_executor final
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
public:
|
||||
static std::string const NAME;
|
||||
|
||||
typedef ::t_daemon t_daemon;
|
||||
|
||||
std::string const & name() const
|
||||
{
|
||||
return NAME;
|
||||
}
|
||||
|
||||
t_daemon create_daemon(boost::program_options::variables_map const & vm)
|
||||
{
|
||||
return t_daemon(vm);
|
||||
}
|
||||
|
||||
bool run_non_interactive(boost::program_options::variables_map const & vm)
|
||||
{
|
||||
return t_daemon(vm).run();
|
||||
}
|
||||
|
||||
bool run_interactive(boost::program_options::variables_map const & vm)
|
||||
{
|
||||
return t_daemon(vm).run();
|
||||
}
|
||||
};
|
||||
|
||||
std::string const t_executor::NAME = "Wallet RPC Daemon";
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
TRY_ENTRY();
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
@ -4761,6 +4716,15 @@ int main(int argc, char** argv) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
return daemonizer::daemonize(argc, const_cast<const char**>(argv), t_executor{}, *vm) ? 0 : 1;
|
||||
daemonizer::run_type run_type = daemonizer::setup_run_environment<tools::wallet_rpc_server>("Wallet RPC Daemon", argc, const_cast<const char **>(argv), *vm);
|
||||
if (run_type == daemonizer::run_type::terminate)
|
||||
return 0;
|
||||
else if (run_type == daemonizer::run_type::terminate_with_error)
|
||||
return -1;
|
||||
|
||||
tools::wallet_rpc_server server(&(*vm));
|
||||
bool result = server.run();
|
||||
return !result;
|
||||
|
||||
CATCH_ENTRY_L0("main", 1);
|
||||
}
|
||||
|
|
|
@ -55,15 +55,16 @@ namespace tools
|
|||
|
||||
static const char* tr(const char* str);
|
||||
|
||||
wallet_rpc_server();
|
||||
wallet_rpc_server(const boost::program_options::variables_map *vm);
|
||||
~wallet_rpc_server();
|
||||
|
||||
bool init(const boost::program_options::variables_map *vm);
|
||||
bool init();
|
||||
bool run();
|
||||
void stop();
|
||||
void set_wallet(wallet2 *cr);
|
||||
|
||||
private:
|
||||
bool run_server_threads();
|
||||
|
||||
CHAIN_HTTP_TO_MAP2(connection_context); //forward http requests to uri map
|
||||
|
||||
|
|
Loading…
Reference in a new issue