2021-03-09 22:24:35 +00:00
|
|
|
#include <llarp/config/config.hpp> // for ensure_config
|
|
|
|
#include <llarp/constants/version.hpp>
|
2019-12-07 19:58:19 +00:00
|
|
|
#include <llarp.hpp>
|
2021-03-09 22:24:35 +00:00
|
|
|
#include <llarp/util/lokinet_init.h>
|
|
|
|
#include <llarp/util/fs.hpp>
|
|
|
|
#include <llarp/util/logging/logger.hpp>
|
|
|
|
#include <llarp/util/logging/ostream_logger.hpp>
|
|
|
|
#include <llarp/util/str.hpp>
|
2019-01-11 01:59:44 +00:00
|
|
|
|
2021-01-11 23:13:22 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
#include <dbghelp.h>
|
|
|
|
#endif
|
|
|
|
|
2019-07-02 21:28:28 +00:00
|
|
|
#include <csignal>
|
2019-01-30 17:24:02 +00:00
|
|
|
|
2019-04-19 18:24:33 +00:00
|
|
|
#include <cxxopts.hpp>
|
2018-07-20 04:50:28 +00:00
|
|
|
#include <string>
|
2018-09-19 13:02:55 +00:00
|
|
|
#include <iostream>
|
2019-10-04 18:10:58 +00:00
|
|
|
#include <future>
|
2018-05-20 16:15:16 +00:00
|
|
|
|
2020-05-21 14:18:23 +00:00
|
|
|
#ifdef USE_JEMALLOC
|
|
|
|
#include <new>
|
|
|
|
#include <jemalloc/jemalloc.h>
|
|
|
|
|
|
|
|
void*
|
|
|
|
operator new(std::size_t sz)
|
|
|
|
{
|
|
|
|
void* ptr = malloc(sz);
|
|
|
|
if (ptr)
|
|
|
|
return ptr;
|
|
|
|
else
|
|
|
|
throw std::bad_alloc{};
|
|
|
|
}
|
|
|
|
void
|
|
|
|
operator delete(void* ptr) noexcept
|
|
|
|
{
|
|
|
|
free(ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
operator delete(void* ptr, size_t) noexcept
|
|
|
|
{
|
|
|
|
free(ptr);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-08-13 17:06:57 +00:00
|
|
|
int
|
|
|
|
lokinet_main(int, char**);
|
2020-08-13 00:49:26 +00:00
|
|
|
|
2018-07-30 04:38:14 +00:00
|
|
|
#ifdef _WIN32
|
2020-08-12 20:27:39 +00:00
|
|
|
#include <strsafe.h>
|
2019-08-02 03:25:48 +00:00
|
|
|
extern "C" LONG FAR PASCAL
|
2020-04-07 18:38:56 +00:00
|
|
|
win32_signal_handler(EXCEPTION_POINTERS*);
|
2020-08-12 18:27:28 +00:00
|
|
|
extern "C" VOID FAR PASCAL
|
|
|
|
win32_daemon_entry(DWORD, LPTSTR*);
|
2020-10-21 13:06:43 +00:00
|
|
|
BOOL ReportSvcStatus(DWORD, DWORD, DWORD);
|
2020-08-13 17:06:57 +00:00
|
|
|
VOID
|
|
|
|
insert_description();
|
|
|
|
SERVICE_STATUS SvcStatus;
|
|
|
|
SERVICE_STATUS_HANDLE SvcStatusHandle;
|
2020-08-12 20:27:39 +00:00
|
|
|
bool start_as_daemon = false;
|
2018-07-30 04:38:14 +00:00
|
|
|
#endif
|
|
|
|
|
2020-06-29 19:55:59 +00:00
|
|
|
std::shared_ptr<llarp::Context> ctx;
|
2020-04-07 18:38:56 +00:00
|
|
|
std::promise<int> exit_code;
|
2018-04-30 16:14:20 +00:00
|
|
|
|
2018-05-22 15:54:19 +00:00
|
|
|
void
|
|
|
|
handle_signal(int sig)
|
2018-05-18 17:50:21 +00:00
|
|
|
{
|
2020-06-29 20:09:59 +00:00
|
|
|
if (ctx)
|
2021-03-02 07:02:59 +00:00
|
|
|
ctx->loop->call([sig] { ctx->HandleSignal(sig); });
|
2020-06-29 20:09:59 +00:00
|
|
|
else
|
|
|
|
std::cerr << "Received signal " << sig << ", but have no context yet. Ignoring!" << std::endl;
|
2018-05-18 17:50:21 +00:00
|
|
|
}
|
|
|
|
|
2018-09-29 08:16:54 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
int
|
|
|
|
startWinsock()
|
|
|
|
{
|
|
|
|
WSADATA wsockd;
|
|
|
|
int err;
|
|
|
|
err = ::WSAStartup(MAKEWORD(2, 2), &wsockd);
|
2020-04-07 18:38:56 +00:00
|
|
|
if (err)
|
2018-09-29 08:16:54 +00:00
|
|
|
{
|
|
|
|
perror("Failed to start Windows Sockets");
|
|
|
|
return err;
|
|
|
|
}
|
2020-01-30 07:36:03 +00:00
|
|
|
::CreateMutex(nullptr, FALSE, "lokinet_win32_daemon");
|
2018-09-29 08:16:54 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2018-12-14 12:50:45 +00:00
|
|
|
|
|
|
|
extern "C" BOOL FAR PASCAL
|
|
|
|
handle_signal_win32(DWORD fdwCtrlType)
|
|
|
|
{
|
|
|
|
UNREFERENCED_PARAMETER(fdwCtrlType);
|
|
|
|
handle_signal(SIGINT);
|
2018-12-23 13:29:11 +00:00
|
|
|
return TRUE; // probably unreachable
|
2018-12-14 12:50:45 +00:00
|
|
|
}
|
2020-08-12 18:00:51 +00:00
|
|
|
|
2020-08-13 17:06:57 +00:00
|
|
|
void
|
|
|
|
install_win32_daemon()
|
2020-08-12 18:00:51 +00:00
|
|
|
{
|
2020-08-12 20:27:39 +00:00
|
|
|
SC_HANDLE schSCManager;
|
|
|
|
SC_HANDLE schService;
|
|
|
|
std::array<char, 1024> szPath{};
|
2020-08-12 18:00:51 +00:00
|
|
|
|
2020-08-13 17:06:57 +00:00
|
|
|
if (!GetModuleFileName(nullptr, szPath.data(), MAX_PATH))
|
2020-08-12 20:27:39 +00:00
|
|
|
{
|
|
|
|
llarp::LogError("Cannot install service ", GetLastError());
|
|
|
|
return;
|
|
|
|
}
|
2020-09-17 19:20:50 +00:00
|
|
|
// just put the flag here. we eat it later on and specify the
|
|
|
|
// config path in the daemon entry point
|
2020-08-12 20:27:39 +00:00
|
|
|
StringCchCat(szPath.data(), 1024, " --win32-daemon");
|
2020-08-12 18:00:51 +00:00
|
|
|
|
2020-08-13 17:06:57 +00:00
|
|
|
// Get a handle to the SCM database.
|
|
|
|
schSCManager = OpenSCManager(
|
|
|
|
nullptr, // local computer
|
|
|
|
nullptr, // ServicesActive database
|
|
|
|
SC_MANAGER_ALL_ACCESS); // full access rights
|
|
|
|
|
|
|
|
if (nullptr == schSCManager)
|
2020-08-12 20:27:39 +00:00
|
|
|
{
|
|
|
|
llarp::LogError("OpenSCManager failed ", GetLastError());
|
|
|
|
return;
|
|
|
|
}
|
2020-08-12 18:00:51 +00:00
|
|
|
|
2020-08-12 20:27:39 +00:00
|
|
|
// Create the service
|
2020-08-13 17:06:57 +00:00
|
|
|
schService = CreateService(
|
|
|
|
schSCManager, // SCM database
|
|
|
|
"lokinet", // name of service
|
|
|
|
"Lokinet for Windows", // service name to display
|
|
|
|
SERVICE_ALL_ACCESS, // desired access
|
|
|
|
SERVICE_WIN32_OWN_PROCESS, // service type
|
|
|
|
SERVICE_DEMAND_START, // start type
|
|
|
|
SERVICE_ERROR_NORMAL, // error control type
|
|
|
|
szPath.data(), // path to service's binary
|
|
|
|
nullptr, // no load ordering group
|
|
|
|
nullptr, // no tag identifier
|
|
|
|
nullptr, // no dependencies
|
|
|
|
nullptr, // LocalSystem account
|
|
|
|
nullptr); // no password
|
|
|
|
|
|
|
|
if (schService == nullptr)
|
2020-08-12 20:27:39 +00:00
|
|
|
{
|
2020-08-13 17:06:57 +00:00
|
|
|
llarp::LogError("CreateService failed ", GetLastError());
|
2020-08-12 18:00:51 +00:00
|
|
|
CloseServiceHandle(schSCManager);
|
2020-08-12 20:27:39 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-08-13 17:06:57 +00:00
|
|
|
else
|
|
|
|
llarp::LogInfo("Service installed successfully");
|
2020-08-12 20:27:39 +00:00
|
|
|
|
2020-08-13 17:06:57 +00:00
|
|
|
CloseServiceHandle(schService);
|
2020-08-13 00:59:37 +00:00
|
|
|
CloseServiceHandle(schSCManager);
|
|
|
|
insert_description();
|
|
|
|
}
|
|
|
|
|
2020-08-13 17:06:57 +00:00
|
|
|
VOID
|
|
|
|
insert_description()
|
2020-08-13 00:59:37 +00:00
|
|
|
{
|
|
|
|
SC_HANDLE schSCManager;
|
|
|
|
SC_HANDLE schService;
|
|
|
|
SERVICE_DESCRIPTION sd;
|
2020-08-13 17:06:57 +00:00
|
|
|
LPTSTR szDesc =
|
|
|
|
"LokiNET is a free, open source, private, "
|
2020-08-13 00:59:37 +00:00
|
|
|
"decentralized, \"market based sybil resistant\" "
|
|
|
|
"and IP based onion routing network";
|
2020-08-13 17:06:57 +00:00
|
|
|
// Get a handle to the SCM database.
|
|
|
|
schSCManager = OpenSCManager(
|
2020-08-13 00:59:37 +00:00
|
|
|
NULL, // local computer
|
2020-08-13 17:06:57 +00:00
|
|
|
NULL, // ServicesActive database
|
|
|
|
SC_MANAGER_ALL_ACCESS); // full access rights
|
|
|
|
|
|
|
|
if (nullptr == schSCManager)
|
2020-08-13 00:59:37 +00:00
|
|
|
{
|
|
|
|
llarp::LogError("OpenSCManager failed ", GetLastError());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get a handle to the service.
|
2020-08-13 17:06:57 +00:00
|
|
|
schService = OpenService(
|
|
|
|
schSCManager, // SCM database
|
|
|
|
"lokinet", // name of service
|
|
|
|
SERVICE_CHANGE_CONFIG); // need change config access
|
|
|
|
|
2020-08-13 00:59:37 +00:00
|
|
|
if (schService == nullptr)
|
2020-08-13 17:06:57 +00:00
|
|
|
{
|
|
|
|
llarp::LogError("OpenService failed ", GetLastError());
|
2020-08-13 00:59:37 +00:00
|
|
|
CloseServiceHandle(schSCManager);
|
|
|
|
return;
|
2020-08-13 17:06:57 +00:00
|
|
|
}
|
2020-08-13 00:59:37 +00:00
|
|
|
|
|
|
|
// Change the service description.
|
|
|
|
sd.lpDescription = szDesc;
|
|
|
|
|
2020-08-13 17:06:57 +00:00
|
|
|
if (!ChangeServiceConfig2(
|
|
|
|
schService, // handle to service
|
|
|
|
SERVICE_CONFIG_DESCRIPTION, // change: description
|
|
|
|
&sd)) // new description
|
2020-08-13 00:59:37 +00:00
|
|
|
{
|
|
|
|
llarp::LogError("ChangeServiceConfig2 failed");
|
|
|
|
}
|
2020-08-13 17:06:57 +00:00
|
|
|
else
|
|
|
|
llarp::LogInfo("Service description updated successfully.");
|
2020-08-13 00:59:37 +00:00
|
|
|
|
2020-08-13 17:06:57 +00:00
|
|
|
CloseServiceHandle(schService);
|
2020-08-12 20:27:39 +00:00
|
|
|
CloseServiceHandle(schSCManager);
|
2020-08-12 18:00:51 +00:00
|
|
|
}
|
|
|
|
|
2020-08-13 17:06:57 +00:00
|
|
|
void
|
|
|
|
uninstall_win32_daemon()
|
2020-08-12 18:00:51 +00:00
|
|
|
{
|
2020-08-12 20:27:39 +00:00
|
|
|
SC_HANDLE schSCManager;
|
|
|
|
SC_HANDLE schService;
|
|
|
|
|
2020-08-13 17:06:57 +00:00
|
|
|
// Get a handle to the SCM database.
|
|
|
|
schSCManager = OpenSCManager(
|
|
|
|
nullptr, // local computer
|
|
|
|
nullptr, // ServicesActive database
|
|
|
|
SC_MANAGER_ALL_ACCESS); // full access rights
|
|
|
|
|
|
|
|
if (nullptr == schSCManager)
|
2020-08-12 20:27:39 +00:00
|
|
|
{
|
|
|
|
llarp::LogError("OpenSCManager failed ", GetLastError());
|
|
|
|
return;
|
|
|
|
}
|
2020-08-12 18:00:51 +00:00
|
|
|
|
2020-08-12 20:27:39 +00:00
|
|
|
// Get a handle to the service.
|
2020-08-13 17:06:57 +00:00
|
|
|
schService = OpenService(
|
|
|
|
schSCManager, // SCM database
|
|
|
|
"lokinet", // name of service
|
|
|
|
0x10000); // need delete access
|
|
|
|
|
2020-08-12 20:27:39 +00:00
|
|
|
if (schService == nullptr)
|
2020-08-13 17:06:57 +00:00
|
|
|
{
|
|
|
|
llarp::LogError("OpenService failed ", GetLastError());
|
2020-08-12 20:27:39 +00:00
|
|
|
CloseServiceHandle(schSCManager);
|
|
|
|
return;
|
|
|
|
}
|
2020-08-12 18:00:51 +00:00
|
|
|
|
2020-08-12 20:27:39 +00:00
|
|
|
// Delete the service.
|
2020-08-13 17:06:57 +00:00
|
|
|
if (!DeleteService(schService))
|
2020-08-12 20:27:39 +00:00
|
|
|
{
|
2020-08-13 17:06:57 +00:00
|
|
|
llarp::LogError("DeleteService failed ", GetLastError());
|
2020-08-12 20:27:39 +00:00
|
|
|
}
|
2020-08-13 17:06:57 +00:00
|
|
|
else
|
|
|
|
llarp::LogInfo("Service deleted successfully\n");
|
|
|
|
|
|
|
|
CloseServiceHandle(schService);
|
2020-08-12 20:27:39 +00:00
|
|
|
CloseServiceHandle(schSCManager);
|
2020-08-12 18:00:51 +00:00
|
|
|
}
|
2018-09-29 08:16:54 +00:00
|
|
|
#endif
|
|
|
|
|
2019-07-26 12:55:08 +00:00
|
|
|
/// this sets up, configures and runs the main context
|
|
|
|
static void
|
2020-10-21 12:58:08 +00:00
|
|
|
run_main_context(std::optional<fs::path> confFile, const llarp::RuntimeOptions opts)
|
2019-07-26 12:55:08 +00:00
|
|
|
{
|
2020-10-21 13:06:43 +00:00
|
|
|
llarp::LogTrace("start of run_main_context()");
|
2020-06-29 19:55:59 +00:00
|
|
|
try
|
2019-07-26 12:55:08 +00:00
|
|
|
{
|
2021-02-02 14:35:40 +00:00
|
|
|
std::shared_ptr<llarp::Config> conf;
|
2020-10-21 12:58:08 +00:00
|
|
|
if (confFile.has_value())
|
|
|
|
{
|
|
|
|
llarp::LogInfo("Using config file: ", *confFile);
|
2021-02-02 14:35:40 +00:00
|
|
|
conf = std::make_shared<llarp::Config>(confFile->parent_path());
|
2020-10-21 12:58:08 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-02-02 14:35:40 +00:00
|
|
|
conf = std::make_shared<llarp::Config>(llarp::GetDefaultDataDir());
|
2020-10-21 12:58:08 +00:00
|
|
|
}
|
2021-03-23 19:00:46 +00:00
|
|
|
if (!conf->Load(confFile, opts.isSNode))
|
Config file improvements (#1397)
* Config file API/comment improvements
API improvements:
=================
Make the config API use position-independent tag parameters (Required,
Default{123}, MultiValue) rather than a sequence of bools with
overloads. For example, instead of:
conf.defineOption<int>("a", "b", false, true, 123, [] { ... });
you now write:
conf.defineOption<int>("a", "b", MultiValue, Default{123}, [] { ... });
The tags are:
- Required
- MultiValue
- Default{value}
plus new abilities (see below):
- Hidden
- RelayOnly
- ClientOnly
- Comment{"line1", "line2", "line3"}
Made option definition more powerful:
=====================================
- `Hidden` allows you to define an option that won't show up in the
generated config file if it isn't set.
- `RelayOnly`/`ClientOnly` sets up an option that is only accepted and
only shows up for relay or client configs. (If neither is specified
the option shows up in both modes).
- `Comment{...}` lets the option comments be specified as part of the
defineOption.
Comment improvements
====================
- Rewrote comments for various options to expand on details.
- Inlined all the comments with the option definitions.
- Several options that were missing comments got comments added.
- Made various options for deprecated and or internal options hidden by
default so that they don't show up in a default config file.
- show the section comment (but not option comments) *after* the
[section] tag instead of before it as it makes more sense that way
(particularly for the [bind] section which has a new long comment to
describe how it works).
Disable profiling by default
============================
We had this weird state where we use and store profiling by default but
never *load* it when starting up. This commit makes us just not use
profiling at all unless explicitly enabled.
Other misc changes:
===================
- change default worker threads to 0 (= num cpus) instead of 1, and fix
it to allow 0.
- Actually apply worker-threads option
- fixed default data-dir value erroneously having quotes around it
- reordered ifname/ifaddr/mapaddr (was previously mapaddr/ifaddr/ifname)
as mapaddr is a sort of specialization of ifaddr and so makes more
sense to come after it (particularly because it now references ifaddr
in its help message).
- removed peer-stats option (since we always require it for relays and
never use it for clients)
- removed router profiles filename option (this doesn't need to be
configurable)
- removed defunct `service-node-seed` option
- Change default logging output file to "" (which means stdout), and
also made "-" work for stdout.
* Router hive compilation fixes
* Comments for SNApp SRV settings in ini file
* Add extra blank line after section comments
* Better deprecated option handling
Allow {client,relay}-only options in {relay,client} configs to be
specified as implicitly deprecated options: they warn, and don't set
anything.
Add an explicit `Deprecated` tag and move deprecated option handling
into definition.cpp.
* Move backwards compat options into section definitions
Keep the "addBackwardsCompatibleConfigOptions" only for options in
sections that no longer exist.
* Fix INI parsing issues & C++17-ify
- don't allow inline comments because it seems they aren't allowed in
ini formats in general, and is going to cause problems if there is a
comment character in a value (e.g. an exit auth string). Additionally
it was breaking on a line such as:
# some comment; see?
because it was treating only `; see?` as the comment and then producing
an error message about the rest of the line being invalid.
- make section parsing stricter: the `[` and `]` have to be at the
beginning at end of the line now (after stripping whitespace).
- Move whitespace stripping to the top since everything in here does it.
- chop off string_view suffix/prefix rather than maintaining position
values
- fix potential infinite loop/segfault when given a line such as `]foo[`
* Make config parsing failure fatal
Load() LogError's and returns false on failure, so we weren't aborting
on config file errors.
* Formatting: allow `{}` for empty functions/structs
Instead of using two lines when empty:
{
}
* Make default dns bind 127.0.0.1 on non-Linux
* Don't show empty section; fix tests
We can conceivably have sections that only make sense for clients or
relays, and so want to completely omit that section if we have no
options for the type of config being generated.
Also fixes missing empty lines between tests.
Co-authored-by: Thomas Winget <tewinget@gmail.com>
2020-10-07 22:22:58 +00:00
|
|
|
throw std::runtime_error{"Config file parsing failed"};
|
2020-06-29 19:55:59 +00:00
|
|
|
|
2020-07-02 15:40:08 +00:00
|
|
|
ctx = std::make_shared<llarp::Context>();
|
2021-02-02 14:35:40 +00:00
|
|
|
ctx->Configure(std::move(conf));
|
2020-06-29 19:55:59 +00:00
|
|
|
|
2019-07-26 12:55:08 +00:00
|
|
|
signal(SIGINT, handle_signal);
|
|
|
|
signal(SIGTERM, handle_signal);
|
|
|
|
#ifndef _WIN32
|
|
|
|
signal(SIGHUP, handle_signal);
|
2021-02-05 21:48:57 +00:00
|
|
|
signal(SIGUSR1, handle_signal);
|
2019-07-26 12:55:08 +00:00
|
|
|
#endif
|
2020-06-29 19:55:59 +00:00
|
|
|
|
2020-07-01 14:38:56 +00:00
|
|
|
ctx->Setup(opts);
|
2020-06-29 19:55:59 +00:00
|
|
|
|
2019-07-26 12:55:08 +00:00
|
|
|
llarp::util::SetThreadName("llarp-mainloop");
|
2020-06-29 19:55:59 +00:00
|
|
|
|
|
|
|
auto result = ctx->Run(opts);
|
|
|
|
exit_code.set_value(result);
|
|
|
|
}
|
|
|
|
catch (std::exception& e)
|
|
|
|
{
|
|
|
|
llarp::LogError("Fatal: caught exception while running: ", e.what());
|
2020-07-01 14:38:33 +00:00
|
|
|
exit_code.set_exception(std::current_exception());
|
2020-06-29 19:55:59 +00:00
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
llarp::LogError("Fatal: caught non-standard exception while running");
|
2020-07-01 14:38:33 +00:00
|
|
|
exit_code.set_exception(std::current_exception());
|
2019-07-26 12:55:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-21 13:06:43 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
void
|
|
|
|
TellWindowsServiceStopped()
|
|
|
|
{
|
|
|
|
::WSACleanup();
|
|
|
|
if (not start_as_daemon)
|
|
|
|
return;
|
|
|
|
|
|
|
|
llarp::LogInfo("Telling Windows the service has stopped.");
|
|
|
|
if (not ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0))
|
|
|
|
{
|
|
|
|
auto error_code = GetLastError();
|
|
|
|
if (error_code == ERROR_INVALID_DATA)
|
|
|
|
llarp::LogError(
|
|
|
|
"SetServiceStatus failed: \"The specified service status structure is invalid.\"");
|
|
|
|
else if (error_code == ERROR_INVALID_HANDLE)
|
|
|
|
llarp::LogError("SetServiceStatus failed: \"The specified handle is invalid.\"");
|
|
|
|
else
|
|
|
|
llarp::LogError("SetServiceStatus failed with an unknown error.");
|
|
|
|
}
|
|
|
|
llarp::LogContext::Instance().ImmediateFlush();
|
|
|
|
}
|
|
|
|
|
|
|
|
class WindowsServiceStopped
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
WindowsServiceStopped() = default;
|
|
|
|
|
|
|
|
~WindowsServiceStopped()
|
|
|
|
{
|
|
|
|
TellWindowsServiceStopped();
|
|
|
|
}
|
|
|
|
};
|
2021-01-11 23:13:22 +00:00
|
|
|
|
|
|
|
/// minidump generation for windows jizz
|
|
|
|
/// will make a coredump when there is an unhandled exception
|
|
|
|
LONG
|
|
|
|
GenerateDump(EXCEPTION_POINTERS* pExceptionPointers)
|
|
|
|
{
|
2021-02-02 18:16:18 +00:00
|
|
|
const DWORD flags = MiniDumpWithFullMemory | MiniDumpWithFullMemoryInfo | MiniDumpWithHandleData
|
|
|
|
| MiniDumpWithUnloadedModules | MiniDumpWithThreadInfo;
|
|
|
|
|
2021-01-11 23:13:22 +00:00
|
|
|
std::stringstream ss;
|
|
|
|
ss << "C:\\ProgramData\\lokinet\\crash-" << llarp::time_now_ms().count() << ".dmp";
|
|
|
|
const std::string fname = ss.str();
|
|
|
|
HANDLE hDumpFile;
|
|
|
|
SYSTEMTIME stLocalTime;
|
|
|
|
GetLocalTime(&stLocalTime);
|
2021-02-02 18:16:18 +00:00
|
|
|
MINIDUMP_EXCEPTION_INFORMATION ExpParam{};
|
2021-01-11 23:13:22 +00:00
|
|
|
|
|
|
|
hDumpFile = CreateFile(
|
|
|
|
fname.c_str(),
|
|
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
|
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|
|
|
0,
|
|
|
|
CREATE_ALWAYS,
|
|
|
|
0,
|
|
|
|
0);
|
|
|
|
|
|
|
|
ExpParam.ExceptionPointers = pExceptionPointers;
|
|
|
|
ExpParam.ClientPointers = TRUE;
|
|
|
|
|
|
|
|
MiniDumpWriteDump(
|
2021-02-02 18:16:18 +00:00
|
|
|
GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, flags, &ExpParam, NULL, NULL);
|
2021-01-11 23:13:22 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-10-21 13:06:43 +00:00
|
|
|
#endif
|
|
|
|
|
2018-05-22 15:54:19 +00:00
|
|
|
int
|
2020-04-07 18:38:56 +00:00
|
|
|
main(int argc, char* argv[])
|
2020-08-13 00:49:26 +00:00
|
|
|
{
|
|
|
|
#ifndef _WIN32
|
|
|
|
return lokinet_main(argc, argv);
|
|
|
|
#else
|
2021-03-05 17:31:52 +00:00
|
|
|
SERVICE_TABLE_ENTRY DispatchTable[] = {
|
|
|
|
{"lokinet", (LPSERVICE_MAIN_FUNCTION)win32_daemon_entry}, {NULL, NULL}};
|
2020-08-13 17:06:57 +00:00
|
|
|
if (lstrcmpi(argv[1], "--win32-daemon") == 0)
|
2020-08-13 00:49:26 +00:00
|
|
|
{
|
|
|
|
start_as_daemon = true;
|
2020-09-17 19:20:50 +00:00
|
|
|
StartServiceCtrlDispatcher(DispatchTable);
|
2020-08-13 00:49:26 +00:00
|
|
|
}
|
2020-08-13 17:06:57 +00:00
|
|
|
else
|
|
|
|
return lokinet_main(argc, argv);
|
2020-08-13 00:49:26 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
lokinet_main(int argc, char* argv[])
|
2018-05-22 15:54:19 +00:00
|
|
|
{
|
2019-11-15 19:40:43 +00:00
|
|
|
auto result = Lokinet_INIT();
|
2020-04-07 18:38:56 +00:00
|
|
|
if (result)
|
2019-11-15 19:40:43 +00:00
|
|
|
{
|
|
|
|
return result;
|
|
|
|
}
|
2020-06-29 19:55:59 +00:00
|
|
|
llarp::RuntimeOptions opts;
|
2018-07-27 00:21:57 +00:00
|
|
|
|
2018-09-29 08:16:54 +00:00
|
|
|
#ifdef _WIN32
|
2020-10-21 13:06:43 +00:00
|
|
|
WindowsServiceStopped stopped_raii;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (startWinsock())
|
2018-09-29 08:16:54 +00:00
|
|
|
return -1;
|
2018-12-14 12:50:45 +00:00
|
|
|
SetConsoleCtrlHandler(handle_signal_win32, TRUE);
|
2020-09-17 19:20:50 +00:00
|
|
|
|
2019-08-02 03:25:48 +00:00
|
|
|
// SetUnhandledExceptionFilter(win32_signal_handler);
|
2018-09-29 08:16:54 +00:00
|
|
|
#endif
|
2020-04-07 20:41:11 +00:00
|
|
|
cxxopts::Options options(
|
|
|
|
"lokinet",
|
|
|
|
"LokiNET is a free, open source, private, "
|
|
|
|
"decentralized, \"market based sybil resistant\" "
|
|
|
|
"and IP based onion routing network");
|
2021-03-23 18:43:33 +00:00
|
|
|
// clang-format off
|
|
|
|
options.add_options()
|
|
|
|
("v,verbose", "Verbose", cxxopts::value<bool>())
|
2020-08-12 18:00:51 +00:00
|
|
|
#ifdef _WIN32
|
2021-03-23 18:43:33 +00:00
|
|
|
("install", "install win32 daemon to SCM", cxxopts::value<bool>())
|
|
|
|
("remove", "remove win32 daemon from SCM", cxxopts::value<bool>())
|
2020-08-12 18:00:51 +00:00
|
|
|
#endif
|
2021-03-23 18:43:33 +00:00
|
|
|
("h,help", "help", cxxopts::value<bool>())("version", "version", cxxopts::value<bool>())
|
|
|
|
("g,generate", "generate client config", cxxopts::value<bool>())
|
|
|
|
("r,router", "run as router instead of client", cxxopts::value<bool>())
|
|
|
|
("f,force", "overwrite", cxxopts::value<bool>())
|
|
|
|
("c,colour", "colour output", cxxopts::value<bool>()->default_value("true"))
|
|
|
|
("b,background", "background mode (start, but do not connect to the network)",
|
|
|
|
cxxopts::value<bool>())
|
|
|
|
("config", "path to configuration file", cxxopts::value<std::string>())
|
|
|
|
;
|
|
|
|
// clang-format on
|
2019-04-21 21:48:28 +00:00
|
|
|
|
|
|
|
options.parse_positional("config");
|
2019-04-19 18:24:33 +00:00
|
|
|
|
2019-10-08 14:52:01 +00:00
|
|
|
bool genconfigOnly = false;
|
2020-04-07 20:41:11 +00:00
|
|
|
bool overwrite = false;
|
2020-10-21 12:58:08 +00:00
|
|
|
std::optional<fs::path> configFile;
|
2019-04-19 18:24:33 +00:00
|
|
|
try
|
2018-09-19 13:02:55 +00:00
|
|
|
{
|
2019-04-19 18:24:33 +00:00
|
|
|
auto result = options.parse(argc, argv);
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (result.count("verbose") > 0)
|
2018-09-19 13:02:55 +00:00
|
|
|
{
|
2019-04-19 18:24:33 +00:00
|
|
|
SetLogLevel(llarp::eLogDebug);
|
|
|
|
llarp::LogDebug("debug logging activated");
|
2018-09-19 13:02:55 +00:00
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!result["colour"].as<bool>())
|
2019-09-16 19:40:31 +00:00
|
|
|
{
|
|
|
|
llarp::LogContext::Instance().logStream =
|
2020-04-07 18:38:56 +00:00
|
|
|
std::make_unique<llarp::OStreamLogStream>(false, std::cerr);
|
2019-09-16 19:40:31 +00:00
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (result.count("help"))
|
2019-04-19 18:24:33 +00:00
|
|
|
{
|
2019-04-23 20:52:13 +00:00
|
|
|
std::cout << options.help() << std::endl;
|
|
|
|
return 0;
|
2019-04-19 18:24:33 +00:00
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (result.count("version"))
|
2019-10-02 18:08:45 +00:00
|
|
|
{
|
2020-06-29 19:55:59 +00:00
|
|
|
std::cout << llarp::VERSION_FULL << std::endl;
|
2019-10-02 18:08:45 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2020-08-12 18:00:51 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
if (result.count("install"))
|
|
|
|
{
|
2020-08-12 20:27:39 +00:00
|
|
|
install_win32_daemon();
|
2020-08-12 18:00:51 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2019-10-02 18:08:45 +00:00
|
|
|
|
2020-08-12 18:00:51 +00:00
|
|
|
if (result.count("remove"))
|
|
|
|
{
|
2020-08-12 20:27:39 +00:00
|
|
|
uninstall_win32_daemon();
|
2020-08-12 18:00:51 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
2020-04-07 18:38:56 +00:00
|
|
|
if (result.count("generate") > 0)
|
2019-04-19 18:24:33 +00:00
|
|
|
{
|
|
|
|
genconfigOnly = true;
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (result.count("background") > 0)
|
2019-05-28 00:19:25 +00:00
|
|
|
{
|
2019-10-04 18:10:58 +00:00
|
|
|
opts.background = true;
|
2019-05-28 00:19:25 +00:00
|
|
|
}
|
|
|
|
|
2020-06-29 19:55:59 +00:00
|
|
|
if (result.count("router") > 0)
|
2020-03-27 01:07:45 +00:00
|
|
|
{
|
2021-03-23 19:00:46 +00:00
|
|
|
opts.isSNode = true;
|
2020-03-27 01:07:45 +00:00
|
|
|
}
|
|
|
|
|
2020-04-07 20:41:11 +00:00
|
|
|
if (result.count("force") > 0)
|
2019-04-19 18:24:33 +00:00
|
|
|
{
|
2020-03-23 20:53:42 +00:00
|
|
|
overwrite = true;
|
2019-04-19 18:24:33 +00:00
|
|
|
}
|
|
|
|
|
2020-04-07 20:41:11 +00:00
|
|
|
if (result.count("config") > 0)
|
2019-04-19 18:24:33 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
auto arg = result["config"].as<std::string>();
|
|
|
|
if (!arg.empty())
|
2019-04-19 18:24:33 +00:00
|
|
|
{
|
2020-06-29 19:55:59 +00:00
|
|
|
configFile = arg;
|
2019-04-19 18:24:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-04-07 18:38:56 +00:00
|
|
|
catch (const cxxopts::option_not_exists_exception& ex)
|
2019-04-19 18:24:33 +00:00
|
|
|
{
|
|
|
|
std::cerr << ex.what();
|
2019-04-23 20:52:13 +00:00
|
|
|
std::cout << options.help() << std::endl;
|
|
|
|
return 1;
|
2019-04-19 18:24:33 +00:00
|
|
|
}
|
2018-09-19 13:02:55 +00:00
|
|
|
|
2020-10-21 12:58:08 +00:00
|
|
|
if (configFile.has_value())
|
2018-09-19 13:02:55 +00:00
|
|
|
{
|
|
|
|
// when we have an explicit filepath
|
2020-10-21 12:58:08 +00:00
|
|
|
fs::path basedir = configFile->parent_path();
|
2020-04-07 20:41:11 +00:00
|
|
|
if (genconfigOnly)
|
2019-11-20 21:22:07 +00:00
|
|
|
{
|
2020-10-30 13:38:17 +00:00
|
|
|
try
|
|
|
|
{
|
2021-03-23 19:00:46 +00:00
|
|
|
llarp::ensureConfig(basedir, *configFile, overwrite, opts.isSNode);
|
2020-10-30 13:38:17 +00:00
|
|
|
}
|
|
|
|
catch (std::exception& ex)
|
|
|
|
{
|
|
|
|
LogError("cannot generate config at ", *configFile, ": ", ex.what());
|
|
|
|
return 1;
|
|
|
|
}
|
2019-11-20 21:22:07 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-10-30 13:38:17 +00:00
|
|
|
try
|
2019-01-29 11:23:40 +00:00
|
|
|
{
|
2020-10-30 13:38:17 +00:00
|
|
|
if (!fs::exists(*configFile))
|
|
|
|
{
|
|
|
|
llarp::LogError("Config file not found ", *configFile);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (std::exception& ex)
|
|
|
|
{
|
|
|
|
LogError("cannot check if ", *configFile, " exists: ", ex.what());
|
2019-11-20 21:22:07 +00:00
|
|
|
return 1;
|
2019-01-29 11:23:40 +00:00
|
|
|
}
|
2018-09-19 13:10:14 +00:00
|
|
|
}
|
2018-09-19 13:02:55 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-10-30 13:38:17 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
llarp::ensureConfig(
|
2021-03-23 19:00:46 +00:00
|
|
|
llarp::GetDefaultDataDir(), llarp::GetDefaultConfigPath(), overwrite, opts.isSNode);
|
2020-10-30 13:38:17 +00:00
|
|
|
}
|
|
|
|
catch (std::exception& ex)
|
|
|
|
{
|
|
|
|
llarp::LogError("cannot ensure config: ", ex.what());
|
|
|
|
return 1;
|
|
|
|
}
|
2020-06-29 19:55:59 +00:00
|
|
|
configFile = llarp::GetDefaultConfigPath();
|
2018-09-19 13:02:55 +00:00
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (genconfigOnly)
|
2019-01-16 20:57:45 +00:00
|
|
|
{
|
2018-09-19 13:02:55 +00:00
|
|
|
return 0;
|
2019-01-16 20:57:45 +00:00
|
|
|
}
|
2018-07-13 13:36:51 +00:00
|
|
|
|
2021-01-11 23:13:22 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
SetUnhandledExceptionFilter(&GenerateDump);
|
|
|
|
#endif
|
|
|
|
|
2021-03-23 18:43:33 +00:00
|
|
|
std::thread main_thread{[&] { run_main_context(configFile, opts); }};
|
2019-07-26 12:55:08 +00:00
|
|
|
auto ftr = exit_code.get_future();
|
2020-10-21 13:06:43 +00:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
|
|
|
|
#endif
|
|
|
|
|
2019-07-26 12:55:08 +00:00
|
|
|
do
|
2018-05-27 18:03:10 +00:00
|
|
|
{
|
2019-07-26 12:55:08 +00:00
|
|
|
// do periodic non lokinet related tasks here
|
2020-06-29 19:55:59 +00:00
|
|
|
if (ctx and ctx->IsUp() and not ctx->LooksAlive())
|
2019-12-07 19:58:19 +00:00
|
|
|
{
|
2021-03-05 17:31:52 +00:00
|
|
|
for (const auto& wtf :
|
2021-03-23 18:43:33 +00:00
|
|
|
{"you have been visited by the mascott of the deadlocked router.",
|
2021-03-05 17:31:52 +00:00
|
|
|
"⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⣀⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠄⠄⠄⠄",
|
|
|
|
"⠄⠄⠄⠄⠄⢀⣀⣀⡀⠄⠄⠄⡠⢲⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡀⠄⠄",
|
|
|
|
"⠄⠄⠄⠔⣈⣀⠄⢔⡒⠳⡴⠊⠄⠸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠿⣿⣿⣧⠄⠄",
|
|
|
|
"⠄⢜⡴⢑⠖⠊⢐⣤⠞⣩⡇⠄⠄⠄⠙⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣆⠄⠝⠛⠋⠐",
|
|
|
|
"⢸⠏⣷⠈⠄⣱⠃⠄⢠⠃⠐⡀⠄⠄⠄⠄⠙⠻⢿⣿⣿⣿⣿⣿⣿⣿⡿⠛⠸⠄⠄⠄⠄",
|
|
|
|
"⠈⣅⠞⢁⣿⢸⠘⡄⡆⠄⠄⠈⠢⡀⠄⠄⠄⠄⠄⠄⠉⠙⠛⠛⠛⠉⠉⡀⠄⠡⢀⠄⣀",
|
|
|
|
"⠄⠙⡎⣹⢸⠄⠆⢘⠁⠄⠄⠄⢸⠈⠢⢄⡀⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠃⠄⠄⠄⠄⠄",
|
|
|
|
"⠄⠄⠑⢿⠈⢆⠘⢼⠄⠄⠄⠄⠸⢐⢾⠄⡘⡏⠲⠆⠠⣤⢤⢤⡤⠄⣖⡇⠄⠄⠄⠄⠄",
|
|
|
|
"⣴⣶⣿⣿⣣⣈⣢⣸⠄⠄⠄⠄⡾⣷⣾⣮⣤⡏⠁⠘⠊⢠⣷⣾⡛⡟⠈⠄⠄⠄⠄⠄⠄",
|
|
|
|
"⣿⣿⣿⣿⣿⠉⠒⢽⠄⠄⠄⠄⡇⣿⣟⣿⡇⠄⠄⠄⠄⢸⣻⡿⡇⡇⠄⠄⠄⠄⠄⠄⠄",
|
|
|
|
"⠻⣿⣿⣿⣿⣄⠰⢼⠄⠄⠄⡄⠁⢻⣍⣯⠃⠄⠄⠄⠄⠈⢿⣻⠃⠈⡆⡄⠄⠄⠄⠄⠄",
|
|
|
|
"⠄⠙⠿⠿⠛⣿⣶⣤⡇⠄⠄⢣⠄⠄⠈⠄⢠⠂⠄⠁⠄⡀⠄⠄⣀⠔⢁⠃⠄⠄⠄⠄⠄",
|
|
|
|
"⠄⠄⠄⠄⠄⣿⣿⣿⣿⣾⠢⣖⣶⣦⣤⣤⣬⣤⣤⣤⣴⣶⣶⡏⠠⢃⠌⠄⠄⠄⠄⠄⠄",
|
|
|
|
"⠄⠄⠄⠄⠄⠿⠿⠟⠛⡹⠉⠛⠛⠿⠿⣿⣿⣿⣿⣿⡿⠂⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄",
|
|
|
|
"⠠⠤⠤⠄⠄⣀⠄⠄⠄⠑⠠⣤⣀⣀⣀⡘⣿⠿⠙⠻⡍⢀⡈⠂⠄⠄⠄⠄⠄⠄⠄⠄⠄",
|
|
|
|
"⠄⠄⠄⠄⠄⠄⠑⠠⣠⣴⣾⣿⣿⣿⣿⣿⣿⣇⠉⠄⠻⣿⣷⣄⡀⠄⠄⠄⠄⠄⠄⠄⠄",
|
|
|
|
"file a bug report now or be cursed with this "
|
|
|
|
"annoying image in your syslog for all time."})
|
2019-12-07 19:58:19 +00:00
|
|
|
{
|
2020-06-29 19:55:59 +00:00
|
|
|
LogError(wtf);
|
|
|
|
llarp::LogContext::Instance().ImmediateFlush();
|
2019-12-07 19:58:19 +00:00
|
|
|
}
|
2020-10-21 13:06:43 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
TellWindowsServiceStopped();
|
|
|
|
#endif
|
2020-06-29 19:55:59 +00:00
|
|
|
std::abort();
|
2019-12-07 19:58:19 +00:00
|
|
|
}
|
2020-04-07 18:38:56 +00:00
|
|
|
} while (ftr.wait_for(std::chrono::seconds(1)) != std::future_status::ready);
|
2019-07-26 12:55:08 +00:00
|
|
|
|
|
|
|
main_thread.join();
|
2020-07-02 15:40:08 +00:00
|
|
|
|
|
|
|
int code = 0;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
code = ftr.get();
|
|
|
|
}
|
|
|
|
catch (const std::exception& e)
|
|
|
|
{
|
|
|
|
std::cerr << "main thread threw exception: " << e.what() << std::endl;
|
|
|
|
code = 1;
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
std::cerr << "main thread threw non-standard exception" << std::endl;
|
|
|
|
code = 2;
|
|
|
|
}
|
2020-04-02 16:47:56 +00:00
|
|
|
|
|
|
|
llarp::LogContext::Instance().ImmediateFlush();
|
2020-04-07 18:38:56 +00:00
|
|
|
if (ctx)
|
2019-12-10 15:21:52 +00:00
|
|
|
{
|
2020-06-29 19:55:59 +00:00
|
|
|
ctx.reset();
|
2019-12-10 15:21:52 +00:00
|
|
|
}
|
2018-05-27 19:13:25 +00:00
|
|
|
return code;
|
2017-09-28 17:02:05 +00:00
|
|
|
}
|
2020-08-12 18:27:28 +00:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
2020-10-21 13:06:43 +00:00
|
|
|
BOOL
|
2020-08-13 17:06:57 +00:00
|
|
|
ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
|
2020-08-12 19:53:29 +00:00
|
|
|
{
|
|
|
|
static DWORD dwCheckPoint = 1;
|
|
|
|
|
|
|
|
// Fill in the SERVICE_STATUS structure.
|
|
|
|
SvcStatus.dwCurrentState = dwCurrentState;
|
|
|
|
SvcStatus.dwWin32ExitCode = dwWin32ExitCode;
|
|
|
|
SvcStatus.dwWaitHint = dwWaitHint;
|
|
|
|
|
|
|
|
if (dwCurrentState == SERVICE_START_PENDING)
|
2020-08-13 17:06:57 +00:00
|
|
|
SvcStatus.dwControlsAccepted = 0;
|
|
|
|
else
|
|
|
|
SvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
|
2020-08-12 19:53:29 +00:00
|
|
|
|
2020-08-13 17:06:57 +00:00
|
|
|
if ((dwCurrentState == SERVICE_RUNNING) || (dwCurrentState == SERVICE_STOPPED))
|
|
|
|
SvcStatus.dwCheckPoint = 0;
|
|
|
|
else
|
|
|
|
SvcStatus.dwCheckPoint = dwCheckPoint++;
|
2020-08-12 19:53:29 +00:00
|
|
|
|
|
|
|
// Report the status of the service to the SCM.
|
2020-10-21 13:06:43 +00:00
|
|
|
return SetServiceStatus(SvcStatusHandle, &SvcStatus);
|
2020-08-12 19:53:29 +00:00
|
|
|
}
|
|
|
|
|
2020-08-13 17:06:57 +00:00
|
|
|
VOID FAR PASCAL
|
|
|
|
SvcCtrlHandler(DWORD dwCtrl)
|
2020-08-12 19:53:29 +00:00
|
|
|
{
|
2020-08-13 17:06:57 +00:00
|
|
|
// Handle the requested control code.
|
|
|
|
|
|
|
|
switch (dwCtrl)
|
|
|
|
{
|
|
|
|
case SERVICE_CONTROL_STOP:
|
|
|
|
ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
|
|
|
|
// Signal the service to stop.
|
|
|
|
handle_signal(SIGINT);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case SERVICE_CONTROL_INTERROGATE:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2020-08-12 19:53:29 +00:00
|
|
|
}
|
|
|
|
|
2020-08-12 18:27:28 +00:00
|
|
|
// The win32 daemon entry point is just a trampoline that returns control
|
|
|
|
// to the original lokinet entry
|
2020-08-12 20:27:39 +00:00
|
|
|
// and only gets called if we get --win32-daemon in the command line
|
2020-08-13 17:06:57 +00:00
|
|
|
VOID FAR PASCAL
|
2020-09-17 19:20:50 +00:00
|
|
|
win32_daemon_entry(DWORD argc, LPTSTR* argv)
|
2020-08-12 18:27:28 +00:00
|
|
|
{
|
2020-08-12 19:53:29 +00:00
|
|
|
// Register the handler function for the service
|
2020-08-13 17:06:57 +00:00
|
|
|
SvcStatusHandle = RegisterServiceCtrlHandler("lokinet", SvcCtrlHandler);
|
2020-08-12 19:53:29 +00:00
|
|
|
|
2020-08-13 17:06:57 +00:00
|
|
|
if (!SvcStatusHandle)
|
|
|
|
{
|
2020-08-13 00:49:26 +00:00
|
|
|
llarp::LogError("failed to register daemon control handler");
|
2020-08-12 19:53:29 +00:00
|
|
|
return;
|
2020-08-13 17:06:57 +00:00
|
|
|
}
|
2020-08-12 19:53:29 +00:00
|
|
|
|
|
|
|
// These SERVICE_STATUS members remain as set here
|
2020-08-13 17:06:57 +00:00
|
|
|
SvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
|
|
|
SvcStatus.dwServiceSpecificExitCode = 0;
|
2020-08-12 19:53:29 +00:00
|
|
|
|
|
|
|
// Report initial status to the SCM
|
2020-09-17 19:20:50 +00:00
|
|
|
ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000);
|
|
|
|
// SCM clobbers startup args, regenerate them here
|
|
|
|
argc = 2;
|
2020-10-21 21:29:46 +00:00
|
|
|
argv[1] = "c:/programdata/lokinet/lokinet.ini";
|
2020-09-17 19:20:50 +00:00
|
|
|
argv[2] = nullptr;
|
|
|
|
lokinet_main(argc, argv);
|
2020-08-12 18:27:28 +00:00
|
|
|
}
|
|
|
|
#endif
|