The Great Wall of Blame

This commit reflects changes to clang-format rules. Unfortunately,
these rule changes create a massive change to the codebase, which
causes an apparent rewrite of git history.

Git blame's --ignore-rev flag can be used to ignore this commit when
attempting to `git blame` some code.
pull/1215/head
Stephen Shelton 4 years ago
parent 30e7c7f828
commit 273270916e
No known key found for this signature in database
GPG Key ID: EE4BADACCE8B631C

@ -14,15 +14,15 @@
namespace namespace
{ {
bool bool
dumpRc(const std::vector< std::string >& files) dumpRc(const std::vector<std::string>& files)
{ {
nlohmann::json result; nlohmann::json result;
for(const auto& file : files) for (const auto& file : files)
{ {
llarp::RouterContact rc; llarp::RouterContact rc;
const bool ret = rc.Read(file.c_str()); const bool ret = rc.Read(file.c_str());
if(ret) if (ret)
{ {
result[file] = rc.ToJson(); result[file] = rc.ToJson();
} }
@ -40,10 +40,10 @@ namespace
size_t size_t
curlCallback(void* contents, size_t size, size_t nmemb, void* userp) noexcept curlCallback(void* contents, size_t size, size_t nmemb, void* userp) noexcept
{ {
auto* str = static_cast< std::string* >(userp); auto* str = static_cast<std::string*>(userp);
size_t realsize = size * nmemb; size_t realsize = size * nmemb;
char* asChar = static_cast< char* >(contents); char* asChar = static_cast<char*>(contents);
std::copy(asChar, asChar + realsize, std::back_inserter(*str)); std::copy(asChar, asChar + realsize, std::back_inserter(*str));
@ -57,13 +57,13 @@ namespace
curl_global_init(CURL_GLOBAL_ALL); curl_global_init(CURL_GLOBAL_ALL);
llarp::Config config; llarp::Config config;
if(!config.Load(configFile.c_str())) if (!config.Load(configFile.c_str()))
{ {
llarp::LogError("Failed to load from config file: ", configFile); llarp::LogError("Failed to load from config file: ", configFile);
return false; return false;
} }
if(!config.api.enableRPCServer()) if (!config.api.enableRPCServer())
{ {
llarp::LogError("Config does not have RPC enabled"); llarp::LogError("Config does not have RPC enabled");
return false; return false;
@ -71,18 +71,15 @@ namespace
std::string address = config.api.rpcBindAddr() + "/jsonrpc"; std::string address = config.api.rpcBindAddr() + "/jsonrpc";
const nlohmann::json request{{"method", command}, const nlohmann::json request{
{"params", nlohmann::json::object()}, {"method", command}, {"params", nlohmann::json::object()}, {"id", "foo"}};
{"id", "foo"}};
const std::string requestStr = request.dump(); const std::string requestStr = request.dump();
std::unique_ptr< curl_slist, void (*)(curl_slist*) > chunk( std::unique_ptr<curl_slist, void (*)(curl_slist*)> chunk(
curl_slist_append(nullptr, "content-type: application/json"), curl_slist_append(nullptr, "content-type: application/json"), &curl_slist_free_all);
&curl_slist_free_all);
std::unique_ptr< CURL, void (*)(CURL*) > curl(curl_easy_init(), std::unique_ptr<CURL, void (*)(CURL*)> curl(curl_easy_init(), &curl_easy_cleanup);
&curl_easy_cleanup);
curl_easy_setopt(curl.get(), CURLOPT_URL, address.c_str()); curl_easy_setopt(curl.get(), CURLOPT_URL, address.c_str());
curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS, requestStr.c_str()); curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS, requestStr.c_str());
curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDSIZE, requestStr.size()); curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDSIZE, requestStr.size());
@ -93,7 +90,7 @@ namespace
curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &result); curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &result);
auto res = curl_easy_perform(curl.get()); auto res = curl_easy_perform(curl.get());
if(res != CURLE_OK) if (res != CURLE_OK)
{ {
llarp::LogError("Failed to curl endpoint, ", curl_easy_strerror(res)); llarp::LogError("Failed to curl endpoint, ", curl_easy_strerror(res));
return false; return false;
@ -109,66 +106,65 @@ namespace
int int
main(int argc, char* argv[]) main(int argc, char* argv[])
{ {
cxxopts::Options options("lokinetctl", cxxopts::Options options(
"LokiNET is a free, open source, private, " "lokinetctl",
"decentralized, \"market based sybil resistant\" " "LokiNET is a free, open source, private, "
"and IP based onion routing network"); "decentralized, \"market based sybil resistant\" "
"and IP based onion routing network");
options.add_options()("v,verbose", "Verbose", cxxopts::value< bool >())(
"h,help", "help", cxxopts::value< bool >())( options.add_options()("v,verbose", "Verbose", cxxopts::value<bool>())(
"c,config", "config file", "h,help", "help", cxxopts::value<bool>())(
cxxopts::value< std::string >()->default_value( "c,config",
llarp::GetDefaultConfigPath().string())) "config file",
cxxopts::value<std::string>()->default_value(llarp::GetDefaultConfigPath().string()))
#ifdef WITH_CURL #ifdef WITH_CURL
("j,jsonrpc", "hit json rpc endpoint", cxxopts::value< std::string >()) ("j,jsonrpc", "hit json rpc endpoint", cxxopts::value<std::string>())
#endif #endif
("dump", "dump rc file", ("dump", "dump rc file", cxxopts::value<std::vector<std::string>>(), "FILE");
cxxopts::value< std::vector< std::string > >(), "FILE");
try try
{ {
const auto result = options.parse(argc, argv); const auto result = options.parse(argc, argv);
if(result.count("verbose") > 0) if (result.count("verbose") > 0)
{ {
SetLogLevel(llarp::eLogDebug); SetLogLevel(llarp::eLogDebug);
llarp::LogContext::Instance().logStream = llarp::LogContext::Instance().logStream =
std::make_unique< llarp::OStreamLogStream >(true, std::cerr); std::make_unique<llarp::OStreamLogStream>(true, std::cerr);
llarp::LogDebug("debug logging activated"); llarp::LogDebug("debug logging activated");
} }
else else
{ {
SetLogLevel(llarp::eLogError); SetLogLevel(llarp::eLogError);
llarp::LogContext::Instance().logStream = llarp::LogContext::Instance().logStream =
std::make_unique< llarp::OStreamLogStream >(true, std::cerr); std::make_unique<llarp::OStreamLogStream>(true, std::cerr);
} }
if(result.count("help") > 0) if (result.count("help") > 0)
{ {
std::cout << options.help() << std::endl; std::cout << options.help() << std::endl;
return 0; return 0;
} }
if(result.count("dump") > 0) if (result.count("dump") > 0)
{ {
if(!dumpRc(result["dump"].as< std::vector< std::string > >())) if (!dumpRc(result["dump"].as<std::vector<std::string>>()))
{ {
return 1; return 1;
} }
} }
#ifdef WITH_CURL #ifdef WITH_CURL
if(result.count("jsonrpc") > 0) if (result.count("jsonrpc") > 0)
{ {
if(!executeJsonRpc(result["jsonrpc"].as< std::string >(), if (!executeJsonRpc(result["jsonrpc"].as<std::string>(), result["config"].as<std::string>()))
result["config"].as< std::string >()))
{ {
return 1; return 1;
} }
} }
#endif #endif
} }
catch(const cxxopts::OptionParseException& ex) catch (const cxxopts::OptionParseException& ex)
{ {
std::cerr << ex.what() << std::endl; std::cerr << ex.what() << std::endl;
std::cout << options.help() << std::endl; std::cout << options.help() << std::endl;

@ -17,16 +17,16 @@
#define wmin(x, y) (((x) < (y)) ? (x) : (y)) #define wmin(x, y) (((x) < (y)) ? (x) : (y))
#define MIN wmin #define MIN wmin
extern "C" LONG FAR PASCAL extern "C" LONG FAR PASCAL
win32_signal_handler(EXCEPTION_POINTERS *); win32_signal_handler(EXCEPTION_POINTERS*);
#endif #endif
struct llarp_main *ctx = 0; struct llarp_main* ctx = 0;
std::promise< int > exit_code; std::promise<int> exit_code;
void void
handle_signal(int sig) handle_signal(int sig)
{ {
if(ctx) if (ctx)
{ {
llarp_main_signal(ctx, sig); llarp_main_signal(ctx, sig);
} }
@ -39,7 +39,7 @@ startWinsock()
WSADATA wsockd; WSADATA wsockd;
int err; int err;
err = ::WSAStartup(MAKEWORD(2, 2), &wsockd); err = ::WSAStartup(MAKEWORD(2, 2), &wsockd);
if(err) if (err)
{ {
perror("Failed to start Windows Sockets"); perror("Failed to start Windows Sockets");
return err; return err;
@ -64,9 +64,9 @@ run_main_context(std::string conffname, llarp_main_runtime_opts opts)
// this is important, can downgrade from Info though // this is important, can downgrade from Info though
llarp::LogDebug("Running from: ", fs::current_path().string()); llarp::LogDebug("Running from: ", fs::current_path().string());
llarp::LogInfo("Using config file: ", conffname); llarp::LogInfo("Using config file: ", conffname);
ctx = llarp_main_init(conffname.c_str()); ctx = llarp_main_init(conffname.c_str());
int code = 1; int code = 1;
if(ctx) if (ctx)
{ {
signal(SIGINT, handle_signal); signal(SIGINT, handle_signal);
signal(SIGTERM, handle_signal); signal(SIGTERM, handle_signal);
@ -75,101 +75,100 @@ run_main_context(std::string conffname, llarp_main_runtime_opts opts)
#endif #endif
code = llarp_main_setup(ctx); code = llarp_main_setup(ctx);
llarp::util::SetThreadName("llarp-mainloop"); llarp::util::SetThreadName("llarp-mainloop");
if(code == 0) if (code == 0)
code = llarp_main_run(ctx, opts); code = llarp_main_run(ctx, opts);
} }
exit_code.set_value(code); exit_code.set_value(code);
} }
int int
main(int argc, char *argv[]) main(int argc, char* argv[])
{ {
auto result = Lokinet_INIT(); auto result = Lokinet_INIT();
if(result) if (result)
{ {
return result; return result;
} }
llarp_main_runtime_opts opts; llarp_main_runtime_opts opts;
const char *singleThreadVar = getenv("LLARP_SHADOW"); const char* singleThreadVar = getenv("LLARP_SHADOW");
if(singleThreadVar && std::string(singleThreadVar) == "1") if (singleThreadVar && std::string(singleThreadVar) == "1")
{ {
opts.singleThreaded = true; opts.singleThreaded = true;
} }
#ifdef _WIN32 #ifdef _WIN32
if(startWinsock()) if (startWinsock())
return -1; return -1;
SetConsoleCtrlHandler(handle_signal_win32, TRUE); SetConsoleCtrlHandler(handle_signal_win32, TRUE);
// SetUnhandledExceptionFilter(win32_signal_handler); // SetUnhandledExceptionFilter(win32_signal_handler);
#endif #endif
cxxopts::Options options("lokinet", cxxopts::Options options(
"LokiNET is a free, open source, private, " "lokinet",
"decentralized, \"market based sybil resistant\" " "LokiNET is a free, open source, private, "
"and IP based onion routing network"); "decentralized, \"market based sybil resistant\" "
options.add_options()("v,verbose", "Verbose", cxxopts::value< bool >())( "and IP based onion routing network");
"h,help", "help", cxxopts::value< bool >())("version", "version", options.add_options()("v,verbose", "Verbose", cxxopts::value<bool>())(
cxxopts::value< bool >())( "h,help", "help", cxxopts::value<bool>())("version", "version", cxxopts::value<bool>())(
"g,generate", "generate client config", cxxopts::value< bool >())( "g,generate", "generate client config", cxxopts::value<bool>())(
"r,router", "generate router config", cxxopts::value< bool >())( "r,router", "generate router config", cxxopts::value<bool>())(
"f,force", "overwrite", cxxopts::value< bool >())( "f,force", "overwrite", cxxopts::value<bool>())(
"c,colour", "colour output", "c,colour", "colour output", cxxopts::value<bool>()->default_value("true"))(
cxxopts::value< bool >()->default_value("true"))(
"b,background", "b,background",
"background mode (start, but do not connect to the network)", "background mode (start, but do not connect to the network)",
cxxopts::value< bool >())("config", "path to configuration file", cxxopts::value<bool>())(
cxxopts::value< std::string >()); "config", "path to configuration file", cxxopts::value<std::string>());
options.parse_positional("config"); options.parse_positional("config");
bool genconfigOnly = false; bool genconfigOnly = false;
bool asRouter = false; bool asRouter = false;
bool overWrite = false; bool overWrite = false;
std::string conffname; std::string conffname;
try try
{ {
auto result = options.parse(argc, argv); auto result = options.parse(argc, argv);
if(result.count("verbose") > 0) if (result.count("verbose") > 0)
{ {
SetLogLevel(llarp::eLogDebug); SetLogLevel(llarp::eLogDebug);
llarp::LogDebug("debug logging activated"); llarp::LogDebug("debug logging activated");
} }
if(!result["colour"].as< bool >()) if (!result["colour"].as<bool>())
{ {
llarp::LogContext::Instance().logStream = llarp::LogContext::Instance().logStream =
std::make_unique< llarp::OStreamLogStream >(false, std::cerr); std::make_unique<llarp::OStreamLogStream>(false, std::cerr);
} }
if(result.count("help")) if (result.count("help"))
{ {
std::cout << options.help() << std::endl; std::cout << options.help() << std::endl;
return 0; return 0;
} }
if(result.count("version")) if (result.count("version"))
{ {
std::cout << llarp_version() << std::endl; std::cout << llarp_version() << std::endl;
return 0; return 0;
} }
if(result.count("generate") > 0) if (result.count("generate") > 0)
{ {
genconfigOnly = true; genconfigOnly = true;
} }
if(result.count("background") > 0) if (result.count("background") > 0)
{ {
opts.background = true; opts.background = true;
} }
if(result.count("force") > 0) if (result.count("force") > 0)
{ {
overWrite = true; overWrite = true;
} }
if(result.count("router") > 0) if (result.count("router") > 0)
{ {
asRouter = true; asRouter = true;
// we should generate and exit (docker needs this, so we don't write a // we should generate and exit (docker needs this, so we don't write a
@ -177,52 +176,50 @@ main(int argc, char *argv[])
genconfigOnly = true; genconfigOnly = true;
} }
if(result.count("config") > 0) if (result.count("config") > 0)
{ {
auto arg = result["config"].as< std::string >(); auto arg = result["config"].as<std::string>();
if(!arg.empty()) if (!arg.empty())
{ {
conffname = arg; conffname = arg;
} }
} }
} }
catch(const cxxopts::option_not_exists_exception &ex) catch (const cxxopts::option_not_exists_exception& ex)
{ {
std::cerr << ex.what(); std::cerr << ex.what();
std::cout << options.help() << std::endl; std::cout << options.help() << std::endl;
return 1; return 1;
} }
if(!conffname.empty()) if (!conffname.empty())
{ {
// when we have an explicit filepath // when we have an explicit filepath
fs::path fname = fs::path(conffname); fs::path fname = fs::path(conffname);
fs::path basedir = fname.parent_path(); fs::path basedir = fname.parent_path();
if(!basedir.empty()) if (!basedir.empty())
{ {
std::error_code ec; std::error_code ec;
if(!fs::create_directories(basedir, ec)) if (!fs::create_directories(basedir, ec))
{ {
if(ec) if (ec)
{ {
llarp::LogError("failed to create '", basedir.string(), llarp::LogError("failed to create '", basedir.string(), "': ", ec.message());
"': ", ec.message());
return 1; return 1;
} }
} }
} }
if(genconfigOnly) if (genconfigOnly)
{ {
if(!llarp_ensure_config(conffname.c_str(), basedir.string().c_str(), if (!llarp_ensure_config(conffname.c_str(), basedir.string().c_str(), overWrite, asRouter))
overWrite, asRouter))
return 1; return 1;
} }
else else
{ {
std::error_code ec; std::error_code ec;
if(!fs::exists(fname, ec)) if (!fs::exists(fname, ec))
{ {
llarp::LogError("Config file not found ", conffname); llarp::LogError("Config file not found ", conffname);
return 1; return 1;
@ -237,12 +234,11 @@ main(int argc, char *argv[])
std::error_code ec; std::error_code ec;
// These paths are guaranteed to exist - $APPDATA or $HOME // These paths are guaranteed to exist - $APPDATA or $HOME
// so only create .lokinet/* // so only create .lokinet/*
if(!fs::create_directory(basepath, ec)) if (!fs::create_directory(basepath, ec))
{ {
if(ec) if (ec)
{ {
llarp::LogError("failed to create '", basepath.string(), llarp::LogError("failed to create '", basepath.string(), "': ", ec.message());
"': ", ec.message());
return 1; return 1;
} }
} }
@ -250,13 +246,13 @@ main(int argc, char *argv[])
auto fpath = llarp::GetDefaultConfigPath(); auto fpath = llarp::GetDefaultConfigPath();
// if using default INI file, we're create it even if you don't ask us too // if using default INI file, we're create it even if you don't ask us too
if(!llarp_ensure_config(fpath.string().c_str(), basepath.string().c_str(), if (!llarp_ensure_config(
overWrite, asRouter)) fpath.string().c_str(), basepath.string().c_str(), overWrite, asRouter))
return 1; return 1;
conffname = fpath.string(); conffname = fpath.string();
} }
if(genconfigOnly) if (genconfigOnly)
{ {
return 0; return 0;
} }
@ -266,33 +262,33 @@ main(int argc, char *argv[])
do do
{ {
// do periodic non lokinet related tasks here // do periodic non lokinet related tasks here
if(ctx != nullptr) if (ctx != nullptr)
{ {
auto ctx_pp = llarp::Context::Get(ctx); auto ctx_pp = llarp::Context::Get(ctx);
if(ctx_pp != nullptr) if (ctx_pp != nullptr)
{ {
if(ctx_pp->IsUp() and not ctx_pp->LooksAlive()) if (ctx_pp->IsUp() and not ctx_pp->LooksAlive())
{ {
for(const auto &wtf : {"you have been visited by the mascott of the " for (const auto& wtf : {"you have been visited by the mascott of the "
"deadlocked router.", "deadlocked router.",
"⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⣀⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠄⠄⠄⠄", "⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⣀⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠄⠄⠄⠄",
"⠄⠄⠄⠄⠄⢀⣀⣀⡀⠄⠄⠄⡠⢲⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡀⠄⠄", "⠄⠄⠄⠄⠄⢀⣀⣀⡀⠄⠄⠄⡠⢲⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡀⠄⠄",
"⠄⠄⠄⠔⣈⣀⠄⢔⡒⠳⡴⠊⠄⠸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠿⣿⣿⣧⠄⠄", "⠄⠄⠄⠔⣈⣀⠄⢔⡒⠳⡴⠊⠄⠸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠿⣿⣿⣧⠄⠄",
"⠄⢜⡴⢑⠖⠊⢐⣤⠞⣩⡇⠄⠄⠄⠙⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣆⠄⠝⠛⠋⠐", "⠄⢜⡴⢑⠖⠊⢐⣤⠞⣩⡇⠄⠄⠄⠙⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣆⠄⠝⠛⠋⠐",
"⢸⠏⣷⠈⠄⣱⠃⠄⢠⠃⠐⡀⠄⠄⠄⠄⠙⠻⢿⣿⣿⣿⣿⣿⣿⣿⡿⠛⠸⠄⠄⠄⠄", "⢸⠏⣷⠈⠄⣱⠃⠄⢠⠃⠐⡀⠄⠄⠄⠄⠙⠻⢿⣿⣿⣿⣿⣿⣿⣿⡿⠛⠸⠄⠄⠄⠄",
"⠈⣅⠞⢁⣿⢸⠘⡄⡆⠄⠄⠈⠢⡀⠄⠄⠄⠄⠄⠄⠉⠙⠛⠛⠛⠉⠉⡀⠄⠡⢀⠄⣀", "⠈⣅⠞⢁⣿⢸⠘⡄⡆⠄⠄⠈⠢⡀⠄⠄⠄⠄⠄⠄⠉⠙⠛⠛⠛⠉⠉⡀⠄⠡⢀⠄⣀",
"⠄⠙⡎⣹⢸⠄⠆⢘⠁⠄⠄⠄⢸⠈⠢⢄⡀⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠃⠄⠄⠄⠄⠄", "⠄⠙⡎⣹⢸⠄⠆⢘⠁⠄⠄⠄⢸⠈⠢⢄⡀⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠃⠄⠄⠄⠄⠄",
"⠄⠄⠑⢿⠈⢆⠘⢼⠄⠄⠄⠄⠸⢐⢾⠄⡘⡏⠲⠆⠠⣤⢤⢤⡤⠄⣖⡇⠄⠄⠄⠄⠄", "⠄⠄⠑⢿⠈⢆⠘⢼⠄⠄⠄⠄⠸⢐⢾⠄⡘⡏⠲⠆⠠⣤⢤⢤⡤⠄⣖⡇⠄⠄⠄⠄⠄",
"⣴⣶⣿⣿⣣⣈⣢⣸⠄⠄⠄⠄⡾⣷⣾⣮⣤⡏⠁⠘⠊⢠⣷⣾⡛⡟⠈⠄⠄⠄⠄⠄⠄", "⣴⣶⣿⣿⣣⣈⣢⣸⠄⠄⠄⠄⡾⣷⣾⣮⣤⡏⠁⠘⠊⢠⣷⣾⡛⡟⠈⠄⠄⠄⠄⠄⠄",
"⣿⣿⣿⣿⣿⠉⠒⢽⠄⠄⠄⠄⡇⣿⣟⣿⡇⠄⠄⠄⠄⢸⣻⡿⡇⡇⠄⠄⠄⠄⠄⠄⠄", "⣿⣿⣿⣿⣿⠉⠒⢽⠄⠄⠄⠄⡇⣿⣟⣿⡇⠄⠄⠄⠄⢸⣻⡿⡇⡇⠄⠄⠄⠄⠄⠄⠄",
"⠻⣿⣿⣿⣿⣄⠰⢼⠄⠄⠄⡄⠁⢻⣍⣯⠃⠄⠄⠄⠄⠈⢿⣻⠃⠈⡆⡄⠄⠄⠄⠄⠄", "⠻⣿⣿⣿⣿⣄⠰⢼⠄⠄⠄⡄⠁⢻⣍⣯⠃⠄⠄⠄⠄⠈⢿⣻⠃⠈⡆⡄⠄⠄⠄⠄⠄",
"⠄⠙⠿⠿⠛⣿⣶⣤⡇⠄⠄⢣⠄⠄⠈⠄⢠⠂⠄⠁⠄⡀⠄⠄⣀⠔⢁⠃⠄⠄⠄⠄⠄", "⠄⠙⠿⠿⠛⣿⣶⣤⡇⠄⠄⢣⠄⠄⠈⠄⢠⠂⠄⠁⠄⡀⠄⠄⣀⠔⢁⠃⠄⠄⠄⠄⠄",
"⠄⠄⠄⠄⠄⣿⣿⣿⣿⣾⠢⣖⣶⣦⣤⣤⣬⣤⣤⣤⣴⣶⣶⡏⠠⢃⠌⠄⠄⠄⠄⠄⠄", "⠄⠄⠄⠄⠄⣿⣿⣿⣿⣾⠢⣖⣶⣦⣤⣤⣬⣤⣤⣤⣴⣶⣶⡏⠠⢃⠌⠄⠄⠄⠄⠄⠄",
"⠄⠄⠄⠄⠄⠿⠿⠟⠛⡹⠉⠛⠛⠿⠿⣿⣿⣿⣿⣿⡿⠂⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄", "⠄⠄⠄⠄⠄⠿⠿⠟⠛⡹⠉⠛⠛⠿⠿⣿⣿⣿⣿⣿⡿⠂⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄",
"⠠⠤⠤⠄⠄⣀⠄⠄⠄⠑⠠⣤⣀⣀⣀⡘⣿⠿⠙⠻⡍⢀⡈⠂⠄⠄⠄⠄⠄⠄⠄⠄⠄", "⠠⠤⠤⠄⠄⣀⠄⠄⠄⠑⠠⣤⣀⣀⣀⡘⣿⠿⠙⠻⡍⢀⡈⠂⠄⠄⠄⠄⠄⠄⠄⠄⠄",
"⠄⠄⠄⠄⠄⠄⠑⠠⣠⣴⣾⣿⣿⣿⣿⣿⣿⣇⠉⠄⠻⣿⣷⣄⡀⠄⠄⠄⠄⠄⠄⠄⠄", "⠄⠄⠄⠄⠄⠄⠑⠠⣠⣴⣾⣿⣿⣿⣿⣿⣿⣇⠉⠄⠻⣿⣷⣄⡀⠄⠄⠄⠄⠄⠄⠄⠄",
"file a bug report now or be cursed with this " "file a bug report now or be cursed with this "
"annoying image in your syslog for all time."}) "annoying image in your syslog for all time."})
{ {
LogError(wtf); LogError(wtf);
} }
@ -300,14 +296,14 @@ main(int argc, char *argv[])
} }
} }
} }
} while(ftr.wait_for(std::chrono::seconds(1)) != std::future_status::ready); } while (ftr.wait_for(std::chrono::seconds(1)) != std::future_status::ready);
main_thread.join(); main_thread.join();
const auto code = ftr.get(); const auto code = ftr.get();
#ifdef _WIN32 #ifdef _WIN32
::WSACleanup(); ::WSACleanup();
#endif #endif
if(ctx) if (ctx)
{ {
llarp_main_free(ctx); llarp_main_free(ctx);
} }

@ -15,8 +15,7 @@ extern "C"
/// if basedir is not nullptr then use basedir as an absolute /// if basedir is not nullptr then use basedir as an absolute
/// base path for all files in config /// base path for all files in config
bool bool
llarp_ensure_config(const char *, const char *, bool overwrite, llarp_ensure_config(const char*, const char*, bool overwrite, bool asrouter);
bool asrouter);
/// llarp application context for C api /// llarp application context for C api
struct llarp_main; struct llarp_main;
@ -24,8 +23,8 @@ extern "C"
/// runtime options for main context from cli /// runtime options for main context from cli
struct llarp_main_runtime_opts struct llarp_main_runtime_opts
{ {
bool background = false; bool background = false;
bool debug = false; bool debug = false;
bool singleThreaded = false; bool singleThreaded = false;
}; };
@ -33,12 +32,12 @@ extern "C"
struct llarp_config; struct llarp_config;
/// get default config for current platform /// get default config for current platform
struct llarp_config * struct llarp_config*
llarp_default_config(); llarp_default_config();
/// free previously allocated configuration /// free previously allocated configuration
void void
llarp_config_free(struct llarp_config *); llarp_config_free(struct llarp_config*);
/// packet writer to send packets to lokinet internals /// packet writer to send packets to lokinet internals
struct llarp_vpn_writer_pipe; struct llarp_vpn_writer_pipe;
@ -52,18 +51,18 @@ extern "C"
struct llarp_vpn_io struct llarp_vpn_io
{ {
/// private implementation /// private implementation
void *impl; void* impl;
/// user data /// user data
void *user; void* user;
/// hook set by user called by lokinet core when lokinet is done with the /// hook set by user called by lokinet core when lokinet is done with the
/// vpn io /// vpn io
void (*closed)(struct llarp_vpn_io *); void (*closed)(struct llarp_vpn_io*);
/// hook set by user called from lokinet core after attempting to inject /// hook set by user called from lokinet core after attempting to inject
/// into endpoint passed a bool set to true if we were injected otherwise /// into endpoint passed a bool set to true if we were injected otherwise
/// set to false /// set to false
void (*injected)(struct llarp_vpn_io *, bool); void (*injected)(struct llarp_vpn_io*, bool);
/// hook set by user called every event loop tick /// hook set by user called every event loop tick
void (*tick)(struct llarp_vpn_io *); void (*tick)(struct llarp_vpn_io*);
}; };
/// info about the network interface that we give to lokinet core /// info about the network interface that we give to lokinet core
@ -80,88 +79,87 @@ extern "C"
/// initialize llarp_vpn_io private implementation /// initialize llarp_vpn_io private implementation
/// returns false if either parameter is nullptr /// returns false if either parameter is nullptr
bool bool
llarp_vpn_io_init(struct llarp_main *m, struct llarp_vpn_io *io); llarp_vpn_io_init(struct llarp_main* m, struct llarp_vpn_io* io);
/// get the packet pipe for writing IP packets to lokinet internals /// get the packet pipe for writing IP packets to lokinet internals
/// returns nullptr if llarp_vpn_io is nullptr or not initialized /// returns nullptr if llarp_vpn_io is nullptr or not initialized
struct llarp_vpn_pkt_writer * struct llarp_vpn_pkt_writer*
llarp_vpn_io_packet_writer(struct llarp_vpn_io *io); llarp_vpn_io_packet_writer(struct llarp_vpn_io* io);
/// get the packet pipe for reading IP packets from lokinet internals /// get the packet pipe for reading IP packets from lokinet internals
/// returns nullptr if llarp_vpn_io is nullptr or not initialized /// returns nullptr if llarp_vpn_io is nullptr or not initialized
struct llarp_vpn_pkt_reader * struct llarp_vpn_pkt_reader*
llarp_vpn_io_packet_reader(struct llarp_vpn_io *io); llarp_vpn_io_packet_reader(struct llarp_vpn_io* io);
/// blocking read on packet reader from lokinet internals /// blocking read on packet reader from lokinet internals
/// returns -1 on error, returns size of packet read /// returns -1 on error, returns size of packet read
/// thread safe /// thread safe
ssize_t ssize_t
llarp_vpn_io_readpkt(struct llarp_vpn_pkt_reader *r, unsigned char *dst, llarp_vpn_io_readpkt(struct llarp_vpn_pkt_reader* r, unsigned char* dst, size_t dstlen);
size_t dstlen);
/// blocking write on packet writer to lokinet internals /// blocking write on packet writer to lokinet internals
/// returns false if we can't write this packet /// returns false if we can't write this packet
/// return true if we wrote this packet /// return true if we wrote this packet
/// thread safe /// thread safe
bool bool
llarp_vpn_io_writepkt(struct llarp_vpn_pkt_writer *w, unsigned char *pktbuf, llarp_vpn_io_writepkt(struct llarp_vpn_pkt_writer* w, unsigned char* pktbuf, size_t pktlen);
size_t pktlen);
/// close vpn io and free private implementation after done /// close vpn io and free private implementation after done
/// operation is async and calls llarp_vpn_io.closed after fully closed /// operation is async and calls llarp_vpn_io.closed after fully closed
/// after fully closed the llarp_vpn_io MUST be re-initialized by /// after fully closed the llarp_vpn_io MUST be re-initialized by
/// llarp_vpn_io_init if it is to be used again /// llarp_vpn_io_init if it is to be used again
void void
llarp_vpn_io_close_async(struct llarp_vpn_io *io); llarp_vpn_io_close_async(struct llarp_vpn_io* io);
/// get the default endpoint's name for injection /// get the default endpoint's name for injection
const char * const char*
llarp_main_get_default_endpoint_name(struct llarp_main *m); llarp_main_get_default_endpoint_name(struct llarp_main* m);
/// give main context a vpn io for mobile when it is reader to do io with /// give main context a vpn io for mobile when it is reader to do io with
/// associated info tries to give the vpn io to endpoint with name epName a /// associated info tries to give the vpn io to endpoint with name epName a
/// deferred call to llarp_vpn_io.injected is queued unconditionally /// deferred call to llarp_vpn_io.injected is queued unconditionally
/// thread safe /// thread safe
bool bool
llarp_main_inject_vpn_by_name(struct llarp_main *m, const char *epName, llarp_main_inject_vpn_by_name(
struct llarp_vpn_io *io, struct llarp_main* m,
struct llarp_vpn_ifaddr_info info); const char* epName,
struct llarp_vpn_io* io,
struct llarp_vpn_ifaddr_info info);
/// give main context a vpn io on its default endpoint /// give main context a vpn io on its default endpoint
static bool static bool
llarp_main_inject_default_vpn(struct llarp_main *m, struct llarp_vpn_io *io, llarp_main_inject_default_vpn(
struct llarp_vpn_ifaddr_info info) struct llarp_main* m, struct llarp_vpn_io* io, struct llarp_vpn_ifaddr_info info)
{ {
return llarp_main_inject_vpn_by_name( return llarp_main_inject_vpn_by_name(m, llarp_main_get_default_endpoint_name(m), io, info);
m, llarp_main_get_default_endpoint_name(m), io, info);
} }
/// load config from file by name /// load config from file by name
/// allocates new config and puts it into c /// allocates new config and puts it into c
/// return false on failure /// return false on failure
bool bool
llarp_config_load_file(const char *fname, struct llarp_config **c); llarp_config_load_file(const char* fname, struct llarp_config** c);
/// loads config from file by name /// loads config from file by name
/// uses already allocated config /// uses already allocated config
/// return false on failure /// return false on failure
bool bool
llarp_config_read_file(struct llarp_config *c, const char *f); llarp_config_read_file(struct llarp_config* c, const char* f);
/// make a main context from configuration /// make a main context from configuration
/// copies config contents /// copies config contents
struct llarp_main * struct llarp_main*
llarp_main_init_from_config(struct llarp_config *conf); llarp_main_init_from_config(struct llarp_config* conf);
/// initialize application context and load config /// initialize application context and load config
static struct llarp_main * static struct llarp_main*
llarp_main_init(const char *fname) llarp_main_init(const char* fname)
{ {
struct llarp_main *m = 0; struct llarp_main* m = 0;
struct llarp_config *conf = 0; struct llarp_config* conf = 0;
if(!llarp_config_load_file(fname, &conf)) if (!llarp_config_load_file(fname, &conf))
return 0; return 0;
if(conf == NULL) if (conf == NULL)
return 0; return 0;
m = llarp_main_init_from_config(conf); m = llarp_main_init_from_config(conf);
llarp_config_free(conf); llarp_config_free(conf);
@ -169,13 +167,13 @@ extern "C"
} }
/// initialize applicatin context with all defaults /// initialize applicatin context with all defaults
static struct llarp_main * static struct llarp_main*
llarp_main_default_init() llarp_main_default_init()
{ {
struct llarp_main *m; struct llarp_main* m;
struct llarp_config *conf; struct llarp_config* conf;
conf = llarp_default_config(); conf = llarp_default_config();
if(conf == 0) if (conf == 0)
return 0; return 0;
m = llarp_main_init_from_config(conf); m = llarp_main_init_from_config(conf);
llarp_config_free(conf); llarp_config_free(conf);
@ -185,36 +183,36 @@ extern "C"
/// (re)configure main context /// (re)configure main context
/// return true if (re)configuration was successful /// return true if (re)configuration was successful
bool bool
llarp_main_configure(struct llarp_main *ptr, struct llarp_config *conf); llarp_main_configure(struct llarp_main* ptr, struct llarp_config* conf);
/// return true if this main context is running /// return true if this main context is running
/// return false otherwise /// return false otherwise
bool bool
llarp_main_is_running(struct llarp_main *ptr); llarp_main_is_running(struct llarp_main* ptr);
/// handle signal for main context /// handle signal for main context
void void
llarp_main_signal(struct llarp_main *ptr, int sig); llarp_main_signal(struct llarp_main* ptr, int sig);
/// setup main context, returns 0 on success /// setup main context, returns 0 on success
int int
llarp_main_setup(struct llarp_main *ptr); llarp_main_setup(struct llarp_main* ptr);
/// run main context, returns 0 on success, blocks until program end /// run main context, returns 0 on success, blocks until program end
int int
llarp_main_run(struct llarp_main *ptr, struct llarp_main_runtime_opts opts); llarp_main_run(struct llarp_main* ptr, struct llarp_main_runtime_opts opts);
/// tell main context to stop and wait for complete stop /// tell main context to stop and wait for complete stop
/// after calling this you can call llarp_main_free safely /// after calling this you can call llarp_main_free safely
void void
llarp_main_stop(struct llarp_main *ptr); llarp_main_stop(struct llarp_main* ptr);
/// free main context and end all operations /// free main context and end all operations
void void
llarp_main_free(struct llarp_main *ptr); llarp_main_free(struct llarp_main* ptr);
/// get version string /// get version string
const char * const char*
llarp_version(); llarp_version();
/// return sizeof(llarp_main); for jni /// return sizeof(llarp_main); for jni

@ -39,23 +39,23 @@ namespace llarp
struct Context struct Context
{ {
/// get context from main pointer /// get context from main pointer
static std::shared_ptr< Context > static std::shared_ptr<Context>
Get(llarp_main *); Get(llarp_main*);
Context() = default; Context() = default;
std::unique_ptr< Crypto > crypto; std::unique_ptr<Crypto> crypto;
std::unique_ptr< CryptoManager > cryptoManager; std::unique_ptr<CryptoManager> cryptoManager;
std::unique_ptr< AbstractRouter > router; std::unique_ptr<AbstractRouter> router;
std::shared_ptr< thread::ThreadPool > worker; std::shared_ptr<thread::ThreadPool> worker;
std::shared_ptr< Logic > logic; std::shared_ptr<Logic> logic;
std::unique_ptr< Config > config; std::unique_ptr<Config> config;
std::unique_ptr< llarp_nodedb > nodedb; std::unique_ptr<llarp_nodedb> nodedb;
llarp_ev_loop_ptr mainloop; llarp_ev_loop_ptr mainloop;
std::string nodedb_dir; std::string nodedb_dir;
bool bool
LoadConfig(const std::string &fname); LoadConfig(const std::string& fname);
void void
Close(); Close();
@ -93,16 +93,16 @@ namespace llarp
/// return true if queued for calling /// return true if queued for calling
/// return false if not queued for calling /// return false if not queued for calling
bool bool
CallSafe(std::function< void(void) > f); CallSafe(std::function<void(void)> f);
#ifdef LOKINET_HIVE #ifdef LOKINET_HIVE
void void
InjectHive(tooling::RouterHive *hive); InjectHive(tooling::RouterHive* hive);
#endif #endif
private: private:
void void
SetPIDFile(const std::string &fname); SetPIDFile(const std::string& fname);
bool bool
WritePIDFile() const; WritePIDFile() const;
@ -118,7 +118,7 @@ namespace llarp
std::string configfile; std::string configfile;
std::string pidfile; std::string pidfile;
std::unique_ptr< std::promise< void > > closeWaiter; std::unique_ptr<std::promise<void>> closeWaiter;
}; };
} // namespace llarp } // namespace llarp

@ -9,7 +9,7 @@ size_t INLINE
strnlen(const char* str, size_t sz) strnlen(const char* str, size_t sz)
{ {
size_t slen = 0; size_t slen = 0;
while(sz-- && str[slen]) while (sz-- && str[slen])
slen++; slen++;
return slen; return slen;
} }

@ -144,9 +144,9 @@ extern "C"
struct device struct device
{ {
/** set me on ios and android to block on a promise for the fd */ /** set me on ios and android to block on a promise for the fd */
int (*obtain_fd)(struct device *); int (*obtain_fd)(struct device*);
/** user data */ /** user data */
void *user; void* user;
t_tun tun_fd; t_tun tun_fd;
int ctrl_sock; int ctrl_sock;
int flags; /* ifr.ifr_flags on Unix */ int flags; /* ifr.ifr_flags on Unix */
@ -166,7 +166,7 @@ extern "C"
}; };
/* User definable log callback */ /* User definable log callback */
typedef void (*t_tuntap_log)(int, int, const char *, const char *); typedef void (*t_tuntap_log)(int, int, const char*, const char*);
TUNTAP_EXPORT t_tuntap_log __tuntap_log; TUNTAP_EXPORT t_tuntap_log __tuntap_log;
#ifndef LOG_TAG #ifndef LOG_TAG
@ -176,90 +176,89 @@ extern "C"
#define tuntap_log(lvl, msg) __tuntap_log(lvl, __LINE__, LOG_TAG, msg) #define tuntap_log(lvl, msg) __tuntap_log(lvl, __LINE__, LOG_TAG, msg)
/* Portable "public" functions */ /* Portable "public" functions */
TUNTAP_EXPORT struct device * TUNTAP_EXPORT struct device*
tuntap_init(void); tuntap_init(void);
TUNTAP_EXPORT int TUNTAP_EXPORT int
tuntap_version(void); tuntap_version(void);
TUNTAP_EXPORT void TUNTAP_EXPORT void
tuntap_destroy(struct device *); tuntap_destroy(struct device*);
TUNTAP_EXPORT void TUNTAP_EXPORT void
tuntap_release(struct device *); tuntap_release(struct device*);
TUNTAP_EXPORT int TUNTAP_EXPORT int
tuntap_start(struct device *, int, int); tuntap_start(struct device*, int, int);
TUNTAP_EXPORT char * TUNTAP_EXPORT char*
tuntap_get_ifname(struct device *); tuntap_get_ifname(struct device*);
TUNTAP_EXPORT int TUNTAP_EXPORT int
tuntap_set_ifname(struct device *, const char *); tuntap_set_ifname(struct device*, const char*);
TUNTAP_EXPORT int TUNTAP_EXPORT int
tuntap_set_descr(struct device *, const char *); tuntap_set_descr(struct device*, const char*);
TUNTAP_EXPORT int TUNTAP_EXPORT int
tuntap_up(struct device *); tuntap_up(struct device*);
TUNTAP_EXPORT int TUNTAP_EXPORT int
tuntap_down(struct device *); tuntap_down(struct device*);
TUNTAP_EXPORT int TUNTAP_EXPORT int
tuntap_get_mtu(struct device *); tuntap_get_mtu(struct device*);
TUNTAP_EXPORT int TUNTAP_EXPORT int
tuntap_set_mtu(struct device *, int); tuntap_set_mtu(struct device*, int);
/** set ip address and netmask /** set ip address and netmask
*/ */
TUNTAP_EXPORT int TUNTAP_EXPORT int
tuntap_set_ip(struct device *, const char *srcaddr, const char *dstaddr, tuntap_set_ip(struct device*, const char* srcaddr, const char* dstaddr, int netmask);
int netmask);
// TUNTAP_EXPORT int tuntap_set_ip_old(struct device *, const char // TUNTAP_EXPORT int tuntap_set_ip_old(struct device *, const char
// *, int); // *, int);
/*TUNTAP_EXPORT int tuntap_set_ip_old(struct device *, const char /*TUNTAP_EXPORT int tuntap_set_ip_old(struct device *, const char
* *, int);*/ * *, int);*/
TUNTAP_EXPORT int TUNTAP_EXPORT int
tuntap_read(struct device *, void *, size_t); tuntap_read(struct device*, void*, size_t);
TUNTAP_EXPORT int TUNTAP_EXPORT int
tuntap_write(struct device *, void *, size_t); tuntap_write(struct device*, void*, size_t);
TUNTAP_EXPORT int TUNTAP_EXPORT int
tuntap_get_readable(struct device *); tuntap_get_readable(struct device*);
TUNTAP_EXPORT int TUNTAP_EXPORT int
tuntap_set_nonblocking(struct device *dev, int); tuntap_set_nonblocking(struct device* dev, int);
TUNTAP_EXPORT int TUNTAP_EXPORT int
tuntap_set_debug(struct device *dev, int); tuntap_set_debug(struct device* dev, int);
/* Logging functions */ /* Logging functions */
TUNTAP_EXPORT void TUNTAP_EXPORT void
tuntap_log_set_cb(t_tuntap_log cb); tuntap_log_set_cb(t_tuntap_log cb);
void void
tuntap_log_default(int, int, const char *, const char *); tuntap_log_default(int, int, const char*, const char*);
void void
tuntap_log_hexdump(void *, size_t); tuntap_log_hexdump(void*, size_t);
void void
tuntap_log_chksum(void *, int); tuntap_log_chksum(void*, int);
/* OS specific functions */ /* OS specific functions */
int int
tuntap_sys_start(struct device *, int, int); tuntap_sys_start(struct device*, int, int);
void void
tuntap_sys_destroy(struct device *); tuntap_sys_destroy(struct device*);
int int
tuntap_sys_set_ipv4(struct device *, t_tun_in_addr *, uint32_t); tuntap_sys_set_ipv4(struct device*, t_tun_in_addr*, uint32_t);
#if defined(Windows) #if defined(Windows)
int int
tuntap_sys_set_dns(struct device *dev, t_tun_in_addr *s, uint32_t mask); tuntap_sys_set_dns(struct device* dev, t_tun_in_addr* s, uint32_t mask);
#endif #endif
#if defined(FreeBSD) #if defined(FreeBSD)
int int
tuntap_sys_set_ipv4_tap(struct device *, t_tun_in_addr *, uint32_t); tuntap_sys_set_ipv4_tap(struct device*, t_tun_in_addr*, uint32_t);
int int
tuntap_sys_set_ipv4_tun(struct device *dev, t_tun_in_addr *s4, tuntap_sys_set_ipv4_tun(
t_tun_in_addr *s4dest, uint32_t bits, int netmask); struct device* dev, t_tun_in_addr* s4, t_tun_in_addr* s4dest, uint32_t bits, int netmask);
#endif #endif
int int
tuntap_sys_set_ipv6(struct device *, t_tun_in6_addr *, uint32_t); tuntap_sys_set_ipv6(struct device*, t_tun_in6_addr*, uint32_t);
int int
tuntap_sys_set_ifname(struct device *, const char *, size_t); tuntap_sys_set_ifname(struct device*, const char*, size_t);
int int
tuntap_sys_set_descr(struct device *, const char *, size_t); tuntap_sys_set_descr(struct device*, const char*, size_t);
#ifdef __cplusplus #ifdef __cplusplus
} }

@ -8,7 +8,7 @@ extern "C"
Java_network_loki_lokinet_LokinetConfig_Obtain(JNIEnv* env, jclass) Java_network_loki_lokinet_LokinetConfig_Obtain(JNIEnv* env, jclass)
{ {
llarp_config* conf = llarp_default_config(); llarp_config* conf = llarp_default_config();
if(conf == nullptr) if (conf == nullptr)
return nullptr; return nullptr;
return env->NewDirectByteBuffer(conf, llarp_config_size()); return env->NewDirectByteBuffer(conf, llarp_config_size());
} }
@ -16,20 +16,19 @@ extern "C"
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_network_loki_lokinet_LokinetConfig_Free(JNIEnv* env, jclass, jobject buf) Java_network_loki_lokinet_LokinetConfig_Free(JNIEnv* env, jclass, jobject buf)
{ {
llarp_config_free(FromBuffer< llarp_config >(env, buf)); llarp_config_free(FromBuffer<llarp_config>(env, buf));
} }
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetConfig_Load(JNIEnv* env, jobject self, Java_network_loki_lokinet_LokinetConfig_Load(JNIEnv* env, jobject self, jstring fname)
jstring fname)
{ {
llarp_config* conf = GetImpl< llarp_config >(env, self); llarp_config* conf = GetImpl<llarp_config>(env, self);
if(conf == nullptr) if (conf == nullptr)
return JNI_FALSE; return JNI_FALSE;
return VisitStringAsStringView< jboolean >( return VisitStringAsStringView<jboolean>(
env, fname, [conf](llarp::string_view val) -> jboolean { env, fname, [conf](llarp::string_view val) -> jboolean {
const auto filename = llarp::string_view_string(val); const auto filename = llarp::string_view_string(val);
if(llarp_config_read_file(conf, filename.c_str())) if (llarp_config_read_file(conf, filename.c_str()))
return JNI_TRUE; return JNI_TRUE;
return JNI_FALSE; return JNI_FALSE;
}); });

@ -6,78 +6,73 @@
extern "C" extern "C"
{ {
JNIEXPORT jobject JNICALL JNIEXPORT jobject JNICALL
Java_network_loki_lokinet_LokinetDaemon_Obtain(JNIEnv *env, jclass) Java_network_loki_lokinet_LokinetDaemon_Obtain(JNIEnv* env, jclass)
{ {
llarp_main *ptr = llarp_main_default_init(); llarp_main* ptr = llarp_main_default_init();
if(ptr == nullptr) if (ptr == nullptr)
return nullptr; return nullptr;
return env->NewDirectByteBuffer(ptr, llarp_main_size()); return env->NewDirectByteBuffer(ptr, llarp_main_size());
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_network_loki_lokinet_LokinetDaemon_Free(JNIEnv *env, jclass, jobject buf) Java_network_loki_lokinet_LokinetDaemon_Free(JNIEnv* env, jclass, jobject buf)
{ {
llarp_main *ptr = FromBuffer< llarp_main >(env, buf); llarp_main* ptr = FromBuffer<llarp_main>(env, buf);
llarp_main_free(ptr); llarp_main_free(ptr);
} }
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetDaemon_Configure(JNIEnv *env, jobject self, Java_network_loki_lokinet_LokinetDaemon_Configure(JNIEnv* env, jobject self, jobject conf)
jobject conf)
{ {
llarp_main *ptr = GetImpl< llarp_main >(env, self); llarp_main* ptr = GetImpl<llarp_main>(env, self);
llarp_config *config = GetImpl< llarp_config >(env, conf); llarp_config* config = GetImpl<llarp_config>(env, conf);
if(ptr == nullptr || config == nullptr) if (ptr == nullptr || config == nullptr)
return JNI_FALSE; return JNI_FALSE;
if(llarp_main_configure(ptr, config)) if (llarp_main_configure(ptr, config))
return JNI_TRUE; return JNI_TRUE;
return llarp_main_setup(ptr) == 0 ? JNI_TRUE : JNI_FALSE; return llarp_main_setup(ptr) == 0 ? JNI_TRUE : JNI_FALSE;
} }
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_network_loki_lokinet_LokinetDaemon_Mainloop(JNIEnv *env, jobject self) Java_network_loki_lokinet_LokinetDaemon_Mainloop(JNIEnv* env, jobject self)
{ {
static llarp_main_runtime_opts opts; static llarp_main_runtime_opts opts;
llarp_main *ptr = GetImpl< llarp_main >(env, self); llarp_main* ptr = GetImpl<llarp_main>(env, self);
if(ptr == nullptr) if (ptr == nullptr)
return -1; return -1;
return llarp_main_run(ptr, opts); return llarp_main_run(ptr, opts);
} }
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetDaemon_IsRunning(JNIEnv *env, jobject self) Java_network_loki_lokinet_LokinetDaemon_IsRunning(JNIEnv* env, jobject self)
{ {
llarp_main *ptr = GetImpl< llarp_main >(env, self); llarp_main* ptr = GetImpl<llarp_main>(env, self);
return (ptr != nullptr && llarp_main_is_running(ptr)) ? JNI_TRUE return (ptr != nullptr && llarp_main_is_running(ptr)) ? JNI_TRUE : JNI_FALSE;
: JNI_FALSE;
} }
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetDaemon_Stop(JNIEnv *env, jobject self) Java_network_loki_lokinet_LokinetDaemon_Stop(JNIEnv* env, jobject self)
{ {
llarp_main *ptr = GetImpl< llarp_main >(env, self); llarp_main* ptr = GetImpl<llarp_main>(env, self);
if(ptr == nullptr) if (ptr == nullptr)
return JNI_FALSE; return JNI_FALSE;
if(not llarp_main_is_running(ptr)) if (not llarp_main_is_running(ptr))
return JNI_FALSE; return JNI_FALSE;
llarp_main_stop(ptr); llarp_main_stop(ptr);
return llarp_main_is_running(ptr) ? JNI_FALSE : JNI_TRUE; return llarp_main_is_running(ptr) ? JNI_FALSE : JNI_TRUE;
} }
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetDaemon_InjectVPN(JNIEnv *env, jobject self, Java_network_loki_lokinet_LokinetDaemon_InjectVPN(JNIEnv* env, jobject self, jobject vpn)
jobject vpn)
{ {
llarp_main *ptr = GetImpl< llarp_main >(env, self); llarp_main* ptr = GetImpl<llarp_main>(env, self);
lokinet_jni_vpnio *impl = GetImpl< lokinet_jni_vpnio >(env, vpn); lokinet_jni_vpnio* impl = GetImpl<lokinet_jni_vpnio>(env, vpn);
if(ptr == nullptr || impl == nullptr) if (ptr == nullptr || impl == nullptr)
return JNI_FALSE; return JNI_FALSE;
if(impl->info.netmask == 0) if (impl->info.netmask == 0)
return JNI_FALSE; return JNI_FALSE;
if(not impl->Init(ptr)) if (not impl->Init(ptr))
return JNI_FALSE; return JNI_FALSE;
return llarp_main_inject_default_vpn(ptr, &impl->io, impl->info) return llarp_main_inject_default_vpn(ptr, &impl->io, impl->info) ? JNI_TRUE : JNI_FALSE;
? JNI_TRUE
: JNI_FALSE;
} }
} }

@ -7,21 +7,19 @@
/// visit string as native bytes /// visit string as native bytes
/// jvm uses some unholy encoding internally so we convert it to utf-8 /// jvm uses some unholy encoding internally so we convert it to utf-8
template < typename T, typename V > template <typename T, typename V>
static T static T
VisitStringAsStringView(JNIEnv* env, jobject str, V visit) VisitStringAsStringView(JNIEnv* env, jobject str, V visit)
{ {
const jclass stringClass = env->GetObjectClass(str); const jclass stringClass = env->GetObjectClass(str);
const jmethodID getBytes = const jmethodID getBytes = env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B");
env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B");
const jstring charsetName = env->NewStringUTF("UTF-8"); const jstring charsetName = env->NewStringUTF("UTF-8");
const jbyteArray stringJbytes = const jbyteArray stringJbytes = (jbyteArray)env->CallObjectMethod(str, getBytes, charsetName);
(jbyteArray)env->CallObjectMethod(str, getBytes, charsetName);
env->DeleteLocalRef(charsetName); env->DeleteLocalRef(charsetName);
const size_t length = env->GetArrayLength(stringJbytes); const size_t length = env->GetArrayLength(stringJbytes);
jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL); jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL);
T result = visit(llarp::string_view((const char*)pBytes, length)); T result = visit(llarp::string_view((const char*)pBytes, length));
@ -32,54 +30,53 @@ VisitStringAsStringView(JNIEnv* env, jobject str, V visit)
} }
/// cast jni buffer to T * /// cast jni buffer to T *
template < typename T > template <typename T>
static T* static T*
FromBuffer(JNIEnv* env, jobject o) FromBuffer(JNIEnv* env, jobject o)
{ {
if(o == nullptr) if (o == nullptr)
return nullptr; return nullptr;
return static_cast< T* >(env->GetDirectBufferAddress(o)); return static_cast<T*>(env->GetDirectBufferAddress(o));
} }
/// get T * from object member called membername /// get T * from object member called membername
template < typename T > template <typename T>
static T* static T*
FromObjectMember(JNIEnv* env, jobject self, const char* membername) FromObjectMember(JNIEnv* env, jobject self, const char* membername)
{ {
jclass cl = env->GetObjectClass(self); jclass cl = env->GetObjectClass(self);
jfieldID name = env->GetFieldID(cl, membername, "Ljava/nio/Buffer;"); jfieldID name = env->GetFieldID(cl, membername, "Ljava/nio/Buffer;");
jobject buffer = env->GetObjectField(self, name); jobject buffer = env->GetObjectField(self, name);
return FromBuffer< T >(env, buffer); return FromBuffer<T>(env, buffer);
} }
/// visit object string member called membername as bytes /// visit object string member called membername as bytes
template < typename T, typename V > template <typename T, typename V>
static T static T
VisitObjectMemberStringAsStringView(JNIEnv* env, jobject self, VisitObjectMemberStringAsStringView(JNIEnv* env, jobject self, const char* membername, V v)
const char* membername, V v)
{ {
jclass cl = env->GetObjectClass(self); jclass cl = env->GetObjectClass(self);
jfieldID name = env->GetFieldID(cl, membername, "Ljava/lang/String;"); jfieldID name = env->GetFieldID(cl, membername, "Ljava/lang/String;");
jobject str = env->GetObjectField(self, name); jobject str = env->GetObjectField(self, name);
return VisitStringAsStringView< T, V >(env, str, v); return VisitStringAsStringView<T, V>(env, str, v);
} }
/// get object member int called membername /// get object member int called membername
template < typename Int_t > template <typename Int_t>
Int_t Int_t
GetObjectMemberAsInt(JNIEnv* env, jobject self, const char* membername) GetObjectMemberAsInt(JNIEnv* env, jobject self, const char* membername)
{ {
jclass cl = env->GetObjectClass(self); jclass cl = env->GetObjectClass(self);
jfieldID name = env->GetFieldID(cl, membername, "I"); jfieldID name = env->GetFieldID(cl, membername, "I");
return env->GetIntField(self, name); return env->GetIntField(self, name);
} }
/// get implementation on jni type /// get implementation on jni type
template < typename T > template <typename T>
T* T*
GetImpl(JNIEnv* env, jobject self) GetImpl(JNIEnv* env, jobject self)
{ {
return FromObjectMember< T >(env, self, "impl"); return FromObjectMember<T>(env, self, "impl");
} }
#endif #endif

@ -12,22 +12,22 @@ namespace lokinet
{ {
struct VPNIO struct VPNIO
{ {
static VPNIO * static VPNIO*
Get(llarp_vpn_io *vpn) Get(llarp_vpn_io* vpn)
{ {
return static_cast< VPNIO * >(vpn->user); return static_cast<VPNIO*>(vpn->user);
} }
virtual ~VPNIO() = default; virtual ~VPNIO() = default;
llarp_vpn_io io; llarp_vpn_io io;
llarp_vpn_ifaddr_info info{{0}, {0}, 0}; llarp_vpn_ifaddr_info info{{0}, {0}, 0};
std::unique_ptr< std::promise< void > > closeWaiter; std::unique_ptr<std::promise<void>> closeWaiter;
void void
Closed() Closed()
{ {
if(closeWaiter) if (closeWaiter)
closeWaiter->set_value(); closeWaiter->set_value();
} }
@ -42,23 +42,23 @@ namespace lokinet
VPNIO() VPNIO()
{ {
io.impl = nullptr; io.impl = nullptr;
io.user = this; io.user = this;
io.closed = [](llarp_vpn_io *vpn) { VPNIO::Get(vpn)->Closed(); }; io.closed = [](llarp_vpn_io* vpn) { VPNIO::Get(vpn)->Closed(); };
io.injected = [](llarp_vpn_io *vpn, bool good) { io.injected = [](llarp_vpn_io* vpn, bool good) {
VPNIO *ptr = VPNIO::Get(vpn); VPNIO* ptr = VPNIO::Get(vpn);
if(good) if (good)
ptr->InjectSuccess(); ptr->InjectSuccess();
else else
ptr->InjectFail(); ptr->InjectFail();
}; };
io.tick = [](llarp_vpn_io *vpn) { VPNIO::Get(vpn)->Tick(); }; io.tick = [](llarp_vpn_io* vpn) { VPNIO::Get(vpn)->Tick(); };
} }
bool bool
Init(llarp_main *ptr) Init(llarp_main* ptr)
{ {
if(Ready()) if (Ready())
return false; return false;
return llarp_vpn_io_init(ptr, &io); return llarp_vpn_io_init(ptr, &io);
} }
@ -72,44 +72,44 @@ namespace lokinet
void void
Close() Close()
{ {
if(not Ready()) if (not Ready())
return; return;
if(closeWaiter) if (closeWaiter)
return; return;
closeWaiter = std::make_unique< std::promise< void > >(); closeWaiter = std::make_unique<std::promise<void>>();
llarp_vpn_io_close_async(&io); llarp_vpn_io_close_async(&io);
closeWaiter->get_future().wait(); closeWaiter->get_future().wait();
closeWaiter.reset(); closeWaiter.reset();
io.impl = nullptr; io.impl = nullptr;
} }
llarp_vpn_pkt_reader * llarp_vpn_pkt_reader*
Reader() Reader()
{ {
return llarp_vpn_io_packet_reader(&io); return llarp_vpn_io_packet_reader(&io);
} }
llarp_vpn_pkt_writer * llarp_vpn_pkt_writer*
Writer() Writer()
{ {
return llarp_vpn_io_packet_writer(&io); return llarp_vpn_io_packet_writer(&io);
} }
ssize_t ssize_t
ReadPacket(void *dst, size_t len) ReadPacket(void* dst, size_t len)
{ {
if(not Ready()) if (not Ready())
return -1; return -1;
unsigned char *buf = (unsigned char *)dst; unsigned char* buf = (unsigned char*)dst;
return llarp_vpn_io_readpkt(Reader(), buf, len); return llarp_vpn_io_readpkt(Reader(), buf, len);
} }
bool bool
WritePacket(void *pkt, size_t len) WritePacket(void* pkt, size_t len)
{ {
if(not Ready()) if (not Ready())
return false; return false;
unsigned char *buf = (unsigned char *)pkt; unsigned char* buf = (unsigned char*)pkt;
return llarp_vpn_io_writepkt(Writer(), buf, len); return llarp_vpn_io_writepkt(Writer(), buf, len);
} }

@ -6,81 +6,78 @@
extern "C" extern "C"
{ {
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_network_loki_lokinet_LokinetVPN_PacketSize(JNIEnv *, jclass) Java_network_loki_lokinet_LokinetVPN_PacketSize(JNIEnv*, jclass)
{ {
return llarp::net::IPPacket::MaxSize; return llarp::net::IPPacket::MaxSize;
} }
JNIEXPORT jobject JNICALL JNIEXPORT jobject JNICALL
Java_network_loki_lokinet_LokinetVPN_Alloc(JNIEnv *env, jclass) Java_network_loki_lokinet_LokinetVPN_Alloc(JNIEnv* env, jclass)
{ {
lokinet_jni_vpnio *vpn = new lokinet_jni_vpnio(); lokinet_jni_vpnio* vpn = new lokinet_jni_vpnio();
return env->NewDirectByteBuffer(vpn, sizeof(lokinet_jni_vpnio)); return env->NewDirectByteBuffer(vpn, sizeof(lokinet_jni_vpnio));
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_network_loki_lokinet_LokinetVPN_Free(JNIEnv *env, jclass, jobject buf) Java_network_loki_lokinet_LokinetVPN_Free(JNIEnv* env, jclass, jobject buf)
{ {
lokinet_jni_vpnio *vpn = FromBuffer< lokinet_jni_vpnio >(env, buf); lokinet_jni_vpnio* vpn = FromBuffer<lokinet_jni_vpnio>(env, buf);
if(vpn == nullptr) if (vpn == nullptr)
return; return;
delete vpn; delete vpn;
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_network_loki_lokinet_LokinetVPN_Stop(JNIEnv *env, jobject self) Java_network_loki_lokinet_LokinetVPN_Stop(JNIEnv* env, jobject self)
{ {
lokinet_jni_vpnio *vpn = GetImpl< lokinet_jni_vpnio >(env, self); lokinet_jni_vpnio* vpn = GetImpl<lokinet_jni_vpnio>(env, self);
if(vpn) if (vpn)
{ {
vpn->Close(); vpn->Close();
} }
} }
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_network_loki_lokinet_LokinetVPN_ReadPkt(JNIEnv *env, jobject self, Java_network_loki_lokinet_LokinetVPN_ReadPkt(JNIEnv* env, jobject self, jobject pkt)
jobject pkt)
{ {
lokinet_jni_vpnio *vpn = GetImpl< lokinet_jni_vpnio >(env, self); lokinet_jni_vpnio* vpn = GetImpl<lokinet_jni_vpnio>(env, self);
if(vpn == nullptr) if (vpn == nullptr)
return -1; return -1;
void *pktbuf = env->GetDirectBufferAddress(pkt); void* pktbuf = env->GetDirectBufferAddress(pkt);
auto pktlen = env->GetDirectBufferCapacity(pkt); auto pktlen = env->GetDirectBufferCapacity(pkt);
if(pktbuf == nullptr) if (pktbuf == nullptr)
return -1; return -1;
return vpn->ReadPacket(pktbuf, pktlen); return vpn->ReadPacket(pktbuf, pktlen);
} }
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetVPN_WritePkt(JNIEnv *env, jobject self, Java_network_loki_lokinet_LokinetVPN_WritePkt(JNIEnv* env, jobject self, jobject pkt)
jobject pkt)
{ {
lokinet_jni_vpnio *vpn = GetImpl< lokinet_jni_vpnio >(env, self); lokinet_jni_vpnio* vpn = GetImpl<lokinet_jni_vpnio>(env, self);
if(vpn == nullptr) if (vpn == nullptr)
return false; return false;
void *pktbuf = env->GetDirectBufferAddress(pkt); void* pktbuf = env->GetDirectBufferAddress(pkt);
auto pktlen = env->GetDirectBufferCapacity(pkt); auto pktlen = env->GetDirectBufferCapacity(pkt);
if(pktbuf == nullptr) if (pktbuf == nullptr)
return false; return false;
return vpn->WritePacket(pktbuf, pktlen); return vpn->WritePacket(pktbuf, pktlen);
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_network_loki_lokinet_LokinetVPN_SetInfo(JNIEnv *env, jobject self, Java_network_loki_lokinet_LokinetVPN_SetInfo(JNIEnv* env, jobject self, jobject info)
jobject info)
{ {
lokinet_jni_vpnio *vpn = GetImpl< lokinet_jni_vpnio >(env, self); lokinet_jni_vpnio* vpn = GetImpl<lokinet_jni_vpnio>(env, self);
if(vpn == nullptr) if (vpn == nullptr)
return; return;
VisitObjectMemberStringAsStringView< bool >( VisitObjectMemberStringAsStringView<bool>(
env, info, "ifaddr", [vpn](llarp::string_view val) -> bool { env, info, "ifaddr", [vpn](llarp::string_view val) -> bool {
vpn->SetIfAddr(val); vpn->SetIfAddr(val);
return true; return true;
}); });
VisitObjectMemberStringAsStringView< bool >( VisitObjectMemberStringAsStringView<bool>(
env, info, "ifname", [vpn](llarp::string_view val) -> bool { env, info, "ifname", [vpn](llarp::string_view val) -> bool {
vpn->SetIfName(val); vpn->SetIfName(val);
return true; return true;
}); });
vpn->info.netmask = GetObjectMemberAsInt< uint8_t >(env, info, "netmask"); vpn->info.netmask = GetObjectMemberAsInt<uint8_t>(env, info, "netmask");
} }
} }

@ -14,7 +14,7 @@ extern "C"
* Signature: ()Ljava/nio/Buffer; * Signature: ()Ljava/nio/Buffer;
*/ */
JNIEXPORT jobject JNICALL JNIEXPORT jobject JNICALL
Java_network_loki_lokinet_LokinetConfig_Obtain(JNIEnv *, jclass); Java_network_loki_lokinet_LokinetConfig_Obtain(JNIEnv*, jclass);
/* /*
* Class: network_loki_lokinet_LokinetConfig * Class: network_loki_lokinet_LokinetConfig
@ -22,7 +22,7 @@ extern "C"
* Signature: (Ljava/nio/Buffer;)V * Signature: (Ljava/nio/Buffer;)V
*/ */
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_network_loki_lokinet_LokinetConfig_Free(JNIEnv *, jclass, jobject); Java_network_loki_lokinet_LokinetConfig_Free(JNIEnv*, jclass, jobject);
/* /*
* Class: network_loki_lokinet_LokinetConfig * Class: network_loki_lokinet_LokinetConfig
@ -30,7 +30,7 @@ extern "C"
* Signature: (Ljava/lang/String;)Z * Signature: (Ljava/lang/String;)Z
*/ */
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetConfig_Load(JNIEnv *, jobject, jstring); Java_network_loki_lokinet_LokinetConfig_Load(JNIEnv*, jobject, jstring);
#ifdef __cplusplus #ifdef __cplusplus
} }

@ -14,7 +14,7 @@ extern "C"
* Signature: ()Ljava/nio/Buffer; * Signature: ()Ljava/nio/Buffer;
*/ */
JNIEXPORT jobject JNICALL JNIEXPORT jobject JNICALL
Java_network_loki_lokinet_LokinetDaemon_Obtain(JNIEnv *, jclass); Java_network_loki_lokinet_LokinetDaemon_Obtain(JNIEnv*, jclass);
/* /*
* Class: network_loki_lokinet_LokinetDaemon * Class: network_loki_lokinet_LokinetDaemon
@ -22,7 +22,7 @@ extern "C"
* Signature: (Ljava/nio/Buffer;)V * Signature: (Ljava/nio/Buffer;)V
*/ */
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_network_loki_lokinet_LokinetDaemon_Free(JNIEnv *, jclass, jobject); Java_network_loki_lokinet_LokinetDaemon_Free(JNIEnv*, jclass, jobject);
/* /*
* Class: network_loki_lokinet_LokinetDaemon * Class: network_loki_lokinet_LokinetDaemon
@ -30,7 +30,7 @@ extern "C"
* Signature: (Lnetwork/loki/lokinet/LokinetConfig;)Z * Signature: (Lnetwork/loki/lokinet/LokinetConfig;)Z
*/ */
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetDaemon_Configure(JNIEnv *, jobject, jobject); Java_network_loki_lokinet_LokinetDaemon_Configure(JNIEnv*, jobject, jobject);
/* /*
* Class: network_loki_lokinet_LokinetDaemon * Class: network_loki_lokinet_LokinetDaemon
@ -38,7 +38,7 @@ extern "C"
* Signature: ()I * Signature: ()I
*/ */
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_network_loki_lokinet_LokinetDaemon_Mainloop(JNIEnv *, jobject); Java_network_loki_lokinet_LokinetDaemon_Mainloop(JNIEnv*, jobject);
/* /*
* Class: network_loki_lokinet_LokinetDaemon * Class: network_loki_lokinet_LokinetDaemon
@ -46,7 +46,7 @@ extern "C"
* Signature: ()Z * Signature: ()Z
*/ */
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetDaemon_IsRunning(JNIEnv *, jobject); Java_network_loki_lokinet_LokinetDaemon_IsRunning(JNIEnv*, jobject);
/* /*
* Class: network_loki_lokinet_LokinetDaemon * Class: network_loki_lokinet_LokinetDaemon
@ -54,7 +54,7 @@ extern "C"
* Signature: ()Z * Signature: ()Z
*/ */
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetDaemon_Stop(JNIEnv *, jobject); Java_network_loki_lokinet_LokinetDaemon_Stop(JNIEnv*, jobject);
/* /*
* Class: network_loki_lokinet_LokinetDaemon * Class: network_loki_lokinet_LokinetDaemon
@ -62,7 +62,7 @@ extern "C"
* Signature: (Lnetwork/loki/lokinet/LokinetVPN;)Z * Signature: (Lnetwork/loki/lokinet/LokinetVPN;)Z
*/ */
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetDaemon_InjectVPN(JNIEnv *, jobject, jobject); Java_network_loki_lokinet_LokinetDaemon_InjectVPN(JNIEnv*, jobject, jobject);
#ifdef __cplusplus #ifdef __cplusplus
} }

@ -14,7 +14,7 @@ extern "C"
* Signature: ()I * Signature: ()I
*/ */
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_network_loki_lokinet_LokinetVPN_PacketSize(JNIEnv *, jclass); Java_network_loki_lokinet_LokinetVPN_PacketSize(JNIEnv*, jclass);
/* /*
* Class: network_loki_lokinet_LokinetVPN * Class: network_loki_lokinet_LokinetVPN
@ -22,7 +22,7 @@ extern "C"
* Signature: ()Ljava/nio/Buffer; * Signature: ()Ljava/nio/Buffer;
*/ */
JNIEXPORT jobject JNICALL JNIEXPORT jobject JNICALL
Java_network_loki_lokinet_LokinetVPN_Alloc(JNIEnv *, jclass); Java_network_loki_lokinet_LokinetVPN_Alloc(JNIEnv*, jclass);
/* /*
* Class: network_loki_lokinet_LokinetVPN * Class: network_loki_lokinet_LokinetVPN
@ -30,7 +30,7 @@ extern "C"
* Signature: (Ljava/nio/Buffer;)V * Signature: (Ljava/nio/Buffer;)V
*/ */
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_network_loki_lokinet_LokinetVPN_Free(JNIEnv *, jclass, jobject); Java_network_loki_lokinet_LokinetVPN_Free(JNIEnv*, jclass, jobject);
/* /*
* Class: network_loki_lokinet_LokinetVPN * Class: network_loki_lokinet_LokinetVPN
@ -38,7 +38,7 @@ extern "C"
* Signature: ()V * Signature: ()V
*/ */
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_network_loki_lokinet_LokinetVPN_Stop(JNIEnv *, jobject); Java_network_loki_lokinet_LokinetVPN_Stop(JNIEnv*, jobject);
/* /*
* Class: network_loki_lokinet_LokinetVPN * Class: network_loki_lokinet_LokinetVPN
@ -46,7 +46,7 @@ extern "C"
* Signature: (Ljava/nio/ByteBuffer;)I * Signature: (Ljava/nio/ByteBuffer;)I
*/ */
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_network_loki_lokinet_LokinetVPN_ReadPkt(JNIEnv *, jobject, jobject); Java_network_loki_lokinet_LokinetVPN_ReadPkt(JNIEnv*, jobject, jobject);
/* /*
* Class: network_loki_lokinet_LokinetVPN * Class: network_loki_lokinet_LokinetVPN
@ -54,7 +54,7 @@ extern "C"
* Signature: (Ljava/nio/ByteBuffer;)Z * Signature: (Ljava/nio/ByteBuffer;)Z
*/ */
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetVPN_WritePkt(JNIEnv *, jobject, jobject); Java_network_loki_lokinet_LokinetVPN_WritePkt(JNIEnv*, jobject, jobject);
/* /*
* Class: network_loki_lokinet_LokinetVPN * Class: network_loki_lokinet_LokinetVPN
@ -62,7 +62,7 @@ extern "C"
* Signature: (Lnetwork/loki/lokinet/LokinetVPN/VPNInfo;)V * Signature: (Lnetwork/loki/lokinet/LokinetVPN/VPNInfo;)V
*/ */
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_network_loki_lokinet_LokinetVPN_SetInfo(JNIEnv *, jobject, jobject); Java_network_loki_lokinet_LokinetVPN_SetInfo(JNIEnv*, jobject, jobject);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -14,7 +14,7 @@ extern "C"
* Signature: ()Ljava/lang/String; * Signature: ()Ljava/lang/String;
*/ */
JNIEXPORT jstring JNICALL JNIEXPORT jstring JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_getABICompiledWith(JNIEnv *, jclass); Java_network_loki_lokinet_Lokinet_1JNI_getABICompiledWith(JNIEnv*, jclass);
/* /*
* Class: network_loki_lokinet_Lokinet_JNI * Class: network_loki_lokinet_Lokinet_JNI
@ -22,14 +22,13 @@ extern "C"
* Signature: (Ljava/lang/String;)Ljava/lang/String; * Signature: (Ljava/lang/String;)Ljava/lang/String;
*/ */
JNIEXPORT jstring JNICALL JNIEXPORT jstring JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_startLokinet(JNIEnv *, jclass, Java_network_loki_lokinet_Lokinet_1JNI_startLokinet(JNIEnv*, jclass, jstring);
jstring);
JNIEXPORT jstring JNICALL JNIEXPORT jstring JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_getIfAddr(JNIEnv *, jclass); Java_network_loki_lokinet_Lokinet_1JNI_getIfAddr(JNIEnv*, jclass);
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_getIfRange(JNIEnv *, jclass); Java_network_loki_lokinet_Lokinet_1JNI_getIfRange(JNIEnv*, jclass);
/* /*
* Class: network_loki_lokinet_Lokinet_JNI * Class: network_loki_lokinet_Lokinet_JNI
@ -37,11 +36,10 @@ extern "C"
* Signature: ()V * Signature: ()V
*/ */
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_stopLokinet(JNIEnv *, jclass); Java_network_loki_lokinet_Lokinet_1JNI_stopLokinet(JNIEnv*, jclass);
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_setVPNFileDescriptor(JNIEnv *, jclass, Java_network_loki_lokinet_Lokinet_1JNI_setVPNFileDescriptor(JNIEnv*, jclass, jint, jint);
jint, jint);
/* /*
* Class: network_loki_lokinet_Lokinet_JNI * Class: network_loki_lokinet_Lokinet_JNI
@ -49,8 +47,7 @@ extern "C"
* Signature: (Z)V * Signature: (Z)V
*/ */
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_onNetworkStateChanged(JNIEnv *, jclass, Java_network_loki_lokinet_Lokinet_1JNI_onNetworkStateChanged(JNIEnv*, jclass, jboolean);
jboolean);
#ifdef __cplusplus #ifdef __cplusplus
} }

@ -19,10 +19,10 @@ namespace abyss
namespace http namespace http
{ {
using RPC_Method_t = std::string; using RPC_Method_t = std::string;
using RPC_Params = nlohmann::json; using RPC_Params = nlohmann::json;
using RPC_Response = nlohmann::json; using RPC_Response = nlohmann::json;
using Headers_t = std::unordered_multimap< std::string, std::string >; using Headers_t = std::unordered_multimap<std::string, std::string>;
using Response = RequestHeader; using Response = RequestHeader;
struct ConnImpl; struct ConnImpl;
/// jsonrpc response handler for client /// jsonrpc response handler for client
@ -60,7 +60,7 @@ namespace abyss
/// jsonrpc client /// jsonrpc client
struct JSONRPC struct JSONRPC
{ {
using HandlerFactory = std::function< IRPCClientHandler*(ConnImpl*) >; using HandlerFactory = std::function<IRPCClientHandler*(ConnImpl*)>;
JSONRPC(); JSONRPC();
~JSONRPC(); ~JSONRPC();
@ -73,8 +73,7 @@ namespace abyss
/// must be called after RunAsync returns true /// must be called after RunAsync returns true
/// queue a call for rpc /// queue a call for rpc
void void
QueueRPC(RPC_Method_t method, RPC_Params params, QueueRPC(RPC_Method_t method, RPC_Params params, HandlerFactory createHandler);
HandlerFactory createHandler);
/// drop all pending calls on the floor /// drop all pending calls on the floor
void void
@ -99,9 +98,7 @@ namespace abyss
struct Call struct Call
{ {
Call(RPC_Method_t&& m, RPC_Params&& p, HandlerFactory&& f) Call(RPC_Method_t&& m, RPC_Params&& p, HandlerFactory&& f)
: method(std::move(m)) : method(std::move(m)), params(std::move(p)), createHandler(std::move(f))
, params(std::move(p))
, createHandler(std::move(f))
{ {
} }
RPC_Method_t method; RPC_Method_t method;
@ -118,11 +115,11 @@ namespace abyss
static void static void
OnTick(llarp_tcp_connecter* connect); OnTick(llarp_tcp_connecter* connect);
std::atomic< bool > m_Run; std::atomic<bool> m_Run;
llarp_tcp_connecter m_connect; llarp_tcp_connecter m_connect;
llarp_ev_loop_ptr m_Loop; llarp_ev_loop_ptr m_Loop;
std::deque< Call > m_PendingCalls; std::deque<Call> m_PendingCalls;
std::list< std::unique_ptr< IRPCClientHandler > > m_Conns; std::list<std::unique_ptr<IRPCClientHandler>> m_Conns;
}; };
} // namespace http } // namespace http
} // namespace abyss } // namespace abyss

@ -12,7 +12,7 @@ namespace abyss
{ {
struct RequestHeader struct RequestHeader
{ {
using Headers_t = std::unordered_multimap< std::string, std::string >; using Headers_t = std::unordered_multimap<std::string, std::string>;
Headers_t Headers; Headers_t Headers;
std::string Method; std::string Method;
std::string Path; std::string Path;

@ -21,18 +21,17 @@ struct MD5
static std::string static std::string
SumHex(const std::string& str) SumHex(const std::string& str)
{ {
std::array< uint8_t, 16 > digest; std::array<uint8_t, 16> digest;
auto dist = str.size(); auto dist = str.size();
MD5 m; MD5 m;
m.Update((const unsigned char*)str.c_str(), dist); m.Update((const unsigned char*)str.c_str(), dist);
m.Final(digest.data()); m.Final(digest.data());
std::string hex; std::string hex;
std::for_each(digest.begin(), digest.end(), std::for_each(digest.begin(), digest.end(), [&hex](const unsigned char& ch) {
[&hex](const unsigned char& ch) { char tmpbuf[4] = {0};
char tmpbuf[4] = {0}; std::snprintf(tmpbuf, sizeof(tmpbuf), "%.2x", ch);
std::snprintf(tmpbuf, sizeof(tmpbuf), "%.2x", ch); hex += std::string(tmpbuf);
hex += std::string(tmpbuf); });
});
return hex; return hex;
} }
}; };

@ -24,7 +24,7 @@ namespace abyss
struct IRPCHandler struct IRPCHandler
{ {
using Method_t = std::string; using Method_t = std::string;
using Params = nlohmann::json; using Params = nlohmann::json;
using Response = nlohmann::json; using Response = nlohmann::json;
IRPCHandler(ConnImpl* impl); IRPCHandler(ConnImpl* impl);
@ -51,8 +51,8 @@ namespace abyss
virtual ~BaseReqHandler(); virtual ~BaseReqHandler();
bool bool
ServeAsync(llarp_ev_loop_ptr loop, std::shared_ptr< llarp::Logic > logic, ServeAsync(
const sockaddr* bindaddr); llarp_ev_loop_ptr loop, std::shared_ptr<llarp::Logic> logic, const sockaddr* bindaddr);
void void
RemoveConn(IRPCHandler* handler); RemoveConn(IRPCHandler* handler);
@ -82,9 +82,9 @@ namespace abyss
OnAccept(struct llarp_tcp_acceptor*, struct llarp_tcp_conn*); OnAccept(struct llarp_tcp_acceptor*, struct llarp_tcp_conn*);
llarp_ev_loop_ptr m_loop; llarp_ev_loop_ptr m_loop;
std::shared_ptr< llarp::Logic > m_Logic; std::shared_ptr<llarp::Logic> m_Logic;
llarp_tcp_acceptor m_acceptor; llarp_tcp_acceptor m_acceptor;
std::list< std::unique_ptr< IRPCHandler > > m_Conns; std::list<std::unique_ptr<IRPCHandler>> m_Conns;
llarp_time_t m_ReqTimeout; llarp_time_t m_ReqTimeout;
}; };
} // namespace httpd } // namespace httpd

@ -13,7 +13,7 @@ struct DemoHandler : public abyss::httpd::IRPCHandler
{ {
} }
nonstd::optional< Response > nonstd::optional<Response>
HandleJSONRPC(Method_t method, const Params& /*params*/) override HandleJSONRPC(Method_t method, const Params& /*params*/) override
{ {
llarp::LogInfo("method: ", method); llarp::LogInfo("method: ", method);
@ -23,14 +23,14 @@ struct DemoHandler : public abyss::httpd::IRPCHandler
struct DemoCall : public abyss::http::IRPCClientHandler struct DemoCall : public abyss::http::IRPCClientHandler
{ {
std::function< void(void) > m_Callback; std::function<void(void)> m_Callback;
std::shared_ptr< llarp::Logic > m_Logic; std::shared_ptr<llarp::Logic> m_Logic;
DemoCall(abyss::http::ConnImpl* impl, std::shared_ptr< llarp::Logic > logic, DemoCall(
std::function< void(void) > callback) abyss::http::ConnImpl* impl,
: abyss::http::IRPCClientHandler(impl) std::shared_ptr<llarp::Logic> logic,
, m_Callback(callback) std::function<void(void)> callback)
, m_Logic(logic) : abyss::http::IRPCClientHandler(impl), m_Callback(callback), m_Logic(logic)
{ {
llarp::LogInfo("new call"); llarp::LogInfo("new call");
} }
@ -57,9 +57,9 @@ struct DemoCall : public abyss::http::IRPCClientHandler
struct DemoClient : public abyss::http::JSONRPC struct DemoClient : public abyss::http::JSONRPC
{ {
llarp_ev_loop_ptr m_Loop; llarp_ev_loop_ptr m_Loop;
std::shared_ptr< llarp::Logic > m_Logic; std::shared_ptr<llarp::Logic> m_Logic;
DemoClient(llarp_ev_loop_ptr l, std::shared_ptr< llarp::Logic > logic) DemoClient(llarp_ev_loop_ptr l, std::shared_ptr<llarp::Logic> logic)
: abyss::http::JSONRPC(), m_Loop(std::move(l)), m_Logic(logic) : abyss::http::JSONRPC(), m_Loop(std::move(l)), m_Logic(logic)
{ {
} }
@ -73,8 +73,10 @@ struct DemoClient : public abyss::http::JSONRPC
void void
DoDemoRequest() DoDemoRequest()
{ {
QueueRPC("test", nlohmann::json::object(), QueueRPC(
std::bind(&DemoClient::NewConn, this, std::placeholders::_1)); "test",
nlohmann::json::object(),
std::bind(&DemoClient::NewConn, this, std::placeholders::_1));
Flush(); Flush();
} }
}; };
@ -104,7 +106,7 @@ main(ABSL_ATTRIBUTE_UNUSED int argc, ABSL_ATTRIBUTE_UNUSED char* argv[])
WSADATA wsockd; WSADATA wsockd;
int err; int err;
err = ::WSAStartup(MAKEWORD(2, 2), &wsockd); err = ::WSAStartup(MAKEWORD(2, 2), &wsockd);
if(err) if (err)
{ {
perror("Failed to start Windows Sockets"); perror("Failed to start Windows Sockets");
return err; return err;
@ -118,18 +120,18 @@ main(ABSL_ATTRIBUTE_UNUSED int argc, ABSL_ATTRIBUTE_UNUSED char* argv[])
// Now that libuv is the single non-Windows event loop impl, we can // Now that libuv is the single non-Windows event loop impl, we can
// go back to using the normal function // go back to using the normal function
llarp_ev_loop_ptr loop = llarp_make_ev_loop(); llarp_ev_loop_ptr loop = llarp_make_ev_loop();
auto logic = std::make_shared< llarp::Logic >(); auto logic = std::make_shared<llarp::Logic>();
sockaddr_in addr; sockaddr_in addr;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.sin_port = htons(1222); addr.sin_port = htons(1222);
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
DemoServer serv; DemoServer serv;
DemoClient client(loop, logic); DemoClient client(loop, logic);
llarp::Addr a(addr); llarp::Addr a(addr);
while(true) while (true)
{ {
llarp::LogInfo("bind to ", a); llarp::LogInfo("bind to ", a);
if(serv.ServeAsync(loop, logic, a)) if (serv.ServeAsync(loop, logic, a))
{ {
client.RunAsync(loop, a.ToString()); client.RunAsync(loop, a.ToString());
client.DoDemoRequest(); client.DoDemoRequest();

@ -17,7 +17,7 @@ namespace abyss
nlohmann::json m_RequestBody; nlohmann::json m_RequestBody;
Headers_t m_SendHeaders; Headers_t m_SendHeaders;
IRPCClientHandler* handler; IRPCClientHandler* handler;
std::unique_ptr< json::IParser > m_BodyParser; std::unique_ptr<json::IParser> m_BodyParser;
nlohmann::json m_Response; nlohmann::json m_Response;
uint16_t m_AuthTries; uint16_t m_AuthTries;
bool m_ShouldAuth; bool m_ShouldAuth;
@ -32,9 +32,12 @@ namespace abyss
State state; State state;
ConnImpl(llarp_tcp_conn* conn, JSONRPC* parent, ConnImpl(
const RPC_Method_t& method, const RPC_Params& params, llarp_tcp_conn* conn,
JSONRPC::HandlerFactory factory) JSONRPC* parent,
const RPC_Method_t& method,
const RPC_Params& params,
JSONRPC::HandlerFactory factory)
: m_Conn(conn) : m_Conn(conn)
, m_Parent(parent) , m_Parent(parent)
, m_RequestBody(nlohmann::json::object()) , m_RequestBody(nlohmann::json::object())
@ -43,17 +46,17 @@ namespace abyss
, m_ShouldAuth(false) , m_ShouldAuth(false)
, state(eInitial) , state(eInitial)
{ {
conn->user = this; conn->user = this;
conn->closed = &ConnImpl::OnClosed; conn->closed = &ConnImpl::OnClosed;
conn->read = &ConnImpl::OnRead; conn->read = &ConnImpl::OnRead;
conn->tick = &ConnImpl::OnTick; conn->tick = &ConnImpl::OnTick;
handler = factory(this); handler = factory(this);
m_RequestBody["jsonrpc"] = "2.0"; m_RequestBody["jsonrpc"] = "2.0";
llarp::AlignedBuffer< 8 > p; llarp::AlignedBuffer<8> p;
p.Randomize(); p.Randomize();
m_RequestBody["id"] = p.ToHex(); m_RequestBody["id"] = p.ToHex();
m_RequestBody["method"] = method; m_RequestBody["method"] = method;
m_RequestBody["params"] = params; m_RequestBody["params"] = params;
} }
@ -62,15 +65,15 @@ namespace abyss
OnClosed(llarp_tcp_conn* conn) OnClosed(llarp_tcp_conn* conn)
{ {
llarp::LogDebug("connection closed"); llarp::LogDebug("connection closed");
ConnImpl* self = static_cast< ConnImpl* >(conn->user); ConnImpl* self = static_cast<ConnImpl*>(conn->user);
self->state = eCloseMe; self->state = eCloseMe;
} }
static void static void
OnRead(llarp_tcp_conn* conn, const llarp_buffer_t& buf) OnRead(llarp_tcp_conn* conn, const llarp_buffer_t& buf)
{ {
ConnImpl* self = static_cast< ConnImpl* >(conn->user); ConnImpl* self = static_cast<ConnImpl*>(conn->user);
if(!self->ProcessRead((const char*)buf.base, buf.sz)) if (!self->ProcessRead((const char*)buf.base, buf.sz))
{ {
self->CloseError("on read failed"); self->CloseError("on read failed");
} }
@ -85,13 +88,13 @@ namespace abyss
ProcessStatusLine(string_view line) ProcessStatusLine(string_view line)
{ {
auto idx = line.find_first_of(' '); auto idx = line.find_first_of(' ');
if(idx == string_view::npos) if (idx == string_view::npos)
return false; return false;
string_view codePart = line.substr(1 + idx); string_view codePart = line.substr(1 + idx);
idx = codePart.find_first_of(' '); idx = codePart.find_first_of(' ');
if(idx == string_view::npos) if (idx == string_view::npos)
return false; return false;
return HandleStatusCode(codePart.substr(0, idx)); return HandleStatusCode(codePart.substr(0, idx));
} }
@ -108,9 +111,9 @@ namespace abyss
bool bool
HandleStatusCode(string_view code) HandleStatusCode(string_view code)
{ {
if(code == string_view("200")) if (code == string_view("200"))
return true; return true;
if(code == string_view("401")) if (code == string_view("401"))
{ {
m_ShouldAuth = true; m_ShouldAuth = true;
return true; return true;
@ -122,21 +125,21 @@ namespace abyss
RetryWithAuth(const std::string& auth) RetryWithAuth(const std::string& auth)
{ {
m_ShouldAuth = false; m_ShouldAuth = false;
auto idx = auth.find_first_of(' '); auto idx = auth.find_first_of(' ');
if(idx == std::string::npos) if (idx == std::string::npos)
return false; return false;
std::istringstream info(auth.substr(1 + idx)); std::istringstream info(auth.substr(1 + idx));
std::unordered_map< std::string, std::string > opts; std::unordered_map<std::string, std::string> opts;
std::string part; std::string part;
while(std::getline(info, part, ',')) while (std::getline(info, part, ','))
{ {
idx = part.find_first_of('='); idx = part.find_first_of('=');
if(idx == std::string::npos) if (idx == std::string::npos)
return false; return false;
std::string k = part.substr(0, idx); std::string k = part.substr(0, idx);
std::string val; std::string val;
++idx; ++idx;
while(idx < part.size()) while (idx < part.size())
{ {
const char ch = part.at(idx); const char ch = part.at(idx);
val += ch; val += ch;
@ -146,48 +149,43 @@ namespace abyss
} }
auto itr = opts.find("algorithm"); auto itr = opts.find("algorithm");
if(itr != opts.end() && itr->second == "MD5-sess") if (itr != opts.end() && itr->second == "MD5-sess")
return false; return false;
std::stringstream authgen; std::stringstream authgen;
auto strip = [&opts](const std::string& name) -> std::string { auto strip = [&opts](const std::string& name) -> std::string {
std::string val; std::string val;
std::for_each(opts[name].begin(), opts[name].end(), std::for_each(opts[name].begin(), opts[name].end(), [&val](const char& ch) {
[&val](const char& ch) { if (ch != '"')
if(ch != '"') val += ch;
val += ch; });
});
return val; return val;
}; };
const auto realm = strip("realm"); const auto realm = strip("realm");
const auto nonce = strip("nonce"); const auto nonce = strip("nonce");
const auto qop = strip("qop"); const auto qop = strip("qop");
std::string nonceCount = "0000000" + std::to_string(m_AuthTries); std::string nonceCount = "0000000" + std::to_string(m_AuthTries);
std::string str = std::string str = m_Parent->username + ":" + realm + ":" + m_Parent->password;
m_Parent->username + ":" + realm + ":" + m_Parent->password;
std::string h1 = MD5::SumHex(str); std::string h1 = MD5::SumHex(str);
str = "POST:/json_rpc"; str = "POST:/json_rpc";
std::string h2 = MD5::SumHex(str); std::string h2 = MD5::SumHex(str);
llarp::AlignedBuffer< 8 > n; llarp::AlignedBuffer<8> n;
n.Randomize(); n.Randomize();
std::string cnonce = n.ToHex(); std::string cnonce = n.ToHex();
str = h1 + ":" + nonce + ":" + nonceCount + ":" + cnonce + ":" + qop str = h1 + ":" + nonce + ":" + nonceCount + ":" + cnonce + ":" + qop + ":" + h2;
+ ":" + h2;
auto responseH = MD5::SumHex(str); auto responseH = MD5::SumHex(str);
authgen << "Digest username=\"" << m_Parent->username + "\", realm=\"" authgen << "Digest username=\"" << m_Parent->username + "\", realm=\"" << realm
<< realm << "\", uri=\"/json_rpc\", algorithm=MD5, qop=auth, nonce=\"" << nonce
<< "\", uri=\"/json_rpc\", algorithm=MD5, qop=auth, nonce=\"" << "\", response=\"" << responseH << "\", nc=" << nonceCount << ", cnonce=\""
<< nonce << "\", response=\"" << responseH << cnonce << "\"";
<< "\", nc=" << nonceCount << ", cnonce=\"" << cnonce << "\""; for (const auto& opt : opts)
for(const auto& opt : opts)
{ {
if(opt.first == "algorithm" || opt.first == "realm" if (opt.first == "algorithm" || opt.first == "realm" || opt.first == "qop"
|| opt.first == "qop" || opt.first == "nonce" || opt.first == "nonce" || opt.first == "stale")
|| opt.first == "stale")
continue; continue;
authgen << ", " << opt.first << "=" << opt.second; authgen << ", " << opt.first << "=" << opt.second;
} }
@ -202,14 +200,14 @@ namespace abyss
ProcessBody(const char* buf, size_t sz) ProcessBody(const char* buf, size_t sz)
{ {
// we got 401 ? // we got 401 ?
if(m_ShouldAuth && m_AuthTries < 9) if (m_ShouldAuth && m_AuthTries < 9)
{ {
m_AuthTries++; m_AuthTries++;
auto range = Header.Headers.equal_range("www-authenticate"); auto range = Header.Headers.equal_range("www-authenticate");
auto itr = range.first; auto itr = range.first;
while(itr != range.second) while (itr != range.second)
{ {
if(RetryWithAuth(itr->second)) if (RetryWithAuth(itr->second))
return true; return true;
else else
++itr; ++itr;
@ -217,19 +215,19 @@ namespace abyss
return false; return false;
} }
// init parser // init parser
if(m_BodyParser == nullptr) if (m_BodyParser == nullptr)
{ {
size_t contentSize = 0; size_t contentSize = 0;
auto itr = Header.Headers.find("content-length"); auto itr = Header.Headers.find("content-length");
// no content-length header // no content-length header
if(itr == Header.Headers.end()) if (itr == Header.Headers.end())
return false; return false;
contentSize = std::stoul(itr->second); contentSize = std::stoul(itr->second);
m_BodyParser.reset(json::MakeParser(contentSize)); m_BodyParser.reset(json::MakeParser(contentSize));
} }
if(m_BodyParser && m_BodyParser->FeedData(buf, sz)) if (m_BodyParser && m_BodyParser->FeedData(buf, sz))
{ {
switch(m_BodyParser->Parse(m_Response)) switch (m_BodyParser->Parse(m_Response))
{ {
case json::IParser::eNeedData: case json::IParser::eNeedData:
return true; return true;
@ -251,30 +249,30 @@ namespace abyss
bool bool
ProcessRead(const char* buf, size_t sz) ProcessRead(const char* buf, size_t sz)
{ {
if(state == eInitial) if (state == eInitial)
return true; return true;
if(!sz) if (!sz)
return true; return true;
bool done = false; bool done = false;
while(state < eReadResponseBody) while (state < eReadResponseBody)
{ {
const char* end = strstr(buf, "\r\n"); const char* end = strstr(buf, "\r\n");
if(!end) if (!end)
return false; return false;
string_view line(buf, end - buf); string_view line(buf, end - buf);
switch(state) switch (state)
{ {
case eReadStatusLine: case eReadStatusLine:
if(!ProcessStatusLine(line)) if (!ProcessStatusLine(line))
return false; return false;
sz -= line.size() + (2 * sizeof(char)); sz -= line.size() + (2 * sizeof(char));
state = eReadResponseHeader; state = eReadResponseHeader;
break; break;
case eReadResponseHeader: case eReadResponseHeader:
if(!ProcessHeaderLine(line, done)) if (!ProcessHeaderLine(line, done))
return false; return false;
sz -= line.size() + (2 * sizeof(char)); sz -= line.size() + (2 * sizeof(char));
if(done) if (done)
state = eReadResponseBody; state = eReadResponseBody;
break; break;
default: default:
@ -283,7 +281,7 @@ namespace abyss
buf = end + (2 * sizeof(char)); buf = end + (2 * sizeof(char));
end = strstr(buf, "\r\n"); end = strstr(buf, "\r\n");
} }
if(state == eReadResponseBody) if (state == eReadResponseBody)
return ProcessBody(buf, sz); return ProcessBody(buf, sz);
return state == eCloseMe; return state == eCloseMe;
} }
@ -298,7 +296,7 @@ namespace abyss
CloseError(const char* msg) CloseError(const char* msg)
{ {
LogError("CloseError: ", msg); LogError("CloseError: ", msg);
if(handler) if (handler)
handler->HandleError(); handler->HandleError();
handler = nullptr; handler = nullptr;
Close(); Close();
@ -307,7 +305,7 @@ namespace abyss
void void
Close() Close()
{ {
if(m_Conn) if (m_Conn)
llarp_tcp_conn_close(m_Conn); llarp_tcp_conn_close(m_Conn);
m_Conn = nullptr; m_Conn = nullptr;
} }
@ -327,13 +325,12 @@ namespace abyss
m_SendHeaders.emplace("Accept", "application/json"); m_SendHeaders.emplace("Accept", "application/json");
std::stringstream request; std::stringstream request;
request << "POST /json_rpc HTTP/1.1\r\n"; request << "POST /json_rpc HTTP/1.1\r\n";
for(const auto& item : m_SendHeaders) for (const auto& item : m_SendHeaders)
request << item.first << ": " << item.second << "\r\n"; request << item.first << ": " << item.second << "\r\n";
request << "\r\n" << body; request << "\r\n" << body;
std::string buf = request.str(); std::string buf = request.str();
if(!llarp_tcp_conn_async_write(m_Conn, if (!llarp_tcp_conn_async_write(m_Conn, llarp_buffer_t(buf.c_str(), buf.size())))
llarp_buffer_t(buf.c_str(), buf.size())))
{ {
CloseError("failed to write request"); CloseError("failed to write request");
return; return;
@ -348,9 +345,9 @@ namespace abyss
{ {
/// close idle connections /// close idle connections
auto itr = m_Conns.begin(); auto itr = m_Conns.begin();
while(itr != m_Conns.end()) while (itr != m_Conns.end())
{ {
if((*itr)->ShouldClose()) if ((*itr)->ShouldClose())
{ {
(*itr)->Close(); (*itr)->Close();
itr = m_Conns.erase(itr); itr = m_Conns.erase(itr);
@ -361,7 +358,7 @@ namespace abyss
// open at most 10 connections // open at most 10 connections
size_t numCalls = std::min(m_PendingCalls.size(), (size_t)10UL); size_t numCalls = std::min(m_PendingCalls.size(), (size_t)10UL);
llarp::LogDebug("tick connect to rpc ", numCalls, " times"); llarp::LogDebug("tick connect to rpc ", numCalls, " times");
while(numCalls--) while (numCalls--)
{ {
llarp_tcp_async_try_connect(m_Loop.get(), &m_connect); llarp_tcp_async_try_connect(m_Loop.get(), &m_connect);
} }
@ -380,13 +377,13 @@ namespace abyss
void void
IRPCClientHandler::Close() const IRPCClientHandler::Close() const
{ {
if(m_Impl) if (m_Impl)
m_Impl->Close(); m_Impl->Close();
} }
IRPCClientHandler::~IRPCClientHandler() IRPCClientHandler::~IRPCClientHandler()
{ {
if(m_Impl) if (m_Impl)
delete m_Impl; delete m_Impl;
} }
@ -400,12 +397,10 @@ namespace abyss
} }
void void
JSONRPC::QueueRPC(RPC_Method_t method, RPC_Params params, JSONRPC::QueueRPC(RPC_Method_t method, RPC_Params params, HandlerFactory createHandler)
HandlerFactory createHandler)
{ {
if(m_Run) if (m_Run)
m_PendingCalls.emplace_back(std::move(method), std::move(params), m_PendingCalls.emplace_back(std::move(method), std::move(params), std::move(createHandler));
std::move(createHandler));
} }
bool bool
@ -414,17 +409,17 @@ namespace abyss
strncpy(m_connect.remote, remote.c_str(), sizeof(m_connect.remote) - 1); strncpy(m_connect.remote, remote.c_str(), sizeof(m_connect.remote) - 1);
// TODO: ipv6 // TODO: ipv6
m_connect.connected = &JSONRPC::OnConnected; m_connect.connected = &JSONRPC::OnConnected;
m_connect.error = &JSONRPC::OnConnectFail; m_connect.error = &JSONRPC::OnConnectFail;
m_connect.user = this; m_connect.user = this;
m_connect.af = AF_INET; m_connect.af = AF_INET;
m_Loop = std::move(loop); m_Loop = std::move(loop);
return true; return true;
} }
void void
JSONRPC::OnConnectFail(llarp_tcp_connecter* tcp) JSONRPC::OnConnectFail(llarp_tcp_connecter* tcp)
{ {
JSONRPC* self = static_cast< JSONRPC* >(tcp->user); JSONRPC* self = static_cast<JSONRPC*>(tcp->user);
llarp::LogError("failed to connect to RPC, dropped all pending calls"); llarp::LogError("failed to connect to RPC, dropped all pending calls");
self->DropAllCalls(); self->DropAllCalls();
} }
@ -432,7 +427,7 @@ namespace abyss
void void
JSONRPC::OnConnected(llarp_tcp_connecter* tcp, llarp_tcp_conn* conn) JSONRPC::OnConnected(llarp_tcp_connecter* tcp, llarp_tcp_conn* conn)
{ {
JSONRPC* self = static_cast< JSONRPC* >(tcp->user); JSONRPC* self = static_cast<JSONRPC*>(tcp->user);
llarp::LogDebug("connected to RPC"); llarp::LogDebug("connected to RPC");
self->Connected(conn); self->Connected(conn);
} }
@ -440,14 +435,14 @@ namespace abyss
void void
JSONRPC::Connected(llarp_tcp_conn* conn) JSONRPC::Connected(llarp_tcp_conn* conn)
{ {
if(!m_Run) if (!m_Run)
{ {
llarp_tcp_conn_close(conn); llarp_tcp_conn_close(conn);
return; return;
} }
auto& front = m_PendingCalls.front(); auto& front = m_PendingCalls.front();
ConnImpl* connimpl = new ConnImpl(conn, this, front.method, front.params, ConnImpl* connimpl =
front.createHandler); new ConnImpl(conn, this, front.method, front.params, front.createHandler);
m_PendingCalls.pop_front(); m_PendingCalls.pop_front();
m_Conns.emplace_back(connimpl->handler); m_Conns.emplace_back(connimpl->handler);
connimpl->SendRequest(); connimpl->SendRequest();
@ -463,9 +458,9 @@ namespace abyss
void void
JSONRPC::DropAllCalls() JSONRPC::DropAllCalls()
{ {
while(m_PendingCalls.size()) while (m_PendingCalls.size())
{ {
auto& front = m_PendingCalls.front(); auto& front = m_PendingCalls.front();
IRPCClientHandler* h = front.createHandler(nullptr); IRPCClientHandler* h = front.createHandler(nullptr);
h->HandleError(); h->HandleError();
delete h; delete h;

@ -7,26 +7,26 @@ namespace abyss
bool bool
HeaderReader::ProcessHeaderLine(string_view line, bool& done) HeaderReader::ProcessHeaderLine(string_view line, bool& done)
{ {
if(line.size() == 0) if (line.size() == 0)
{ {
done = true; done = true;
return true; return true;
} }
auto idx = line.find_first_of(':'); auto idx = line.find_first_of(':');
if(idx == string_view::npos) if (idx == string_view::npos)
return false; return false;
string_view header = line.substr(0, idx); string_view header = line.substr(0, idx);
string_view val = line.substr(1 + idx); string_view val = line.substr(1 + idx);
// to lowercase // to lowercase
std::string lowerHeader; std::string lowerHeader;
lowerHeader.reserve(header.size()); lowerHeader.reserve(header.size());
auto itr = header.begin(); auto itr = header.begin();
while(itr != header.end()) while (itr != header.end())
{ {
lowerHeader += std::tolower(*itr); lowerHeader += std::tolower(*itr);
++itr; ++itr;
} }
if(ShouldProcessHeader(lowerHeader)) if (ShouldProcessHeader(lowerHeader))
{ {
val = val.substr(val.find_first_not_of(' ')); val = val.substr(val.find_first_not_of(' '));
// llarp::str() here for gcc 5 compat // llarp::str() here for gcc 5 compat

@ -4,15 +4,13 @@ using UINT4 = uint32_t;
/* forward declaration */ /* forward declaration */
void void
Transform(uint32_t *buf, uint32_t *in); Transform(uint32_t* buf, uint32_t* in);
static unsigned char PADDING[64] = { static unsigned char PADDING[64] = {
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/* F, G and H are basic MD5 functions: selection, majority, parity */ /* F, G and H are basic MD5 functions: selection, majority, parity */
#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
@ -63,7 +61,7 @@ MD5::MD5()
} }
void void
MD5::Update(const unsigned char *inBuf, uint32_t inLen) MD5::Update(const unsigned char* inBuf, uint32_t inLen)
{ {
UINT4 input[16]; UINT4 input[16];
int mdi; int mdi;
@ -72,20 +70,20 @@ MD5::Update(const unsigned char *inBuf, uint32_t inLen)
mdi = (int)((this->i[0] >> 3) & 0x3F); mdi = (int)((this->i[0] >> 3) & 0x3F);
/* update number of bits */ /* update number of bits */
if((this->i[0] + ((UINT4)inLen << 3)) < this->i[0]) if ((this->i[0] + ((UINT4)inLen << 3)) < this->i[0])
this->i[1]++; this->i[1]++;
this->i[0] += ((UINT4)inLen << 3); this->i[0] += ((UINT4)inLen << 3);
this->i[1] += ((UINT4)inLen >> 29); this->i[1] += ((UINT4)inLen >> 29);
while(inLen--) while (inLen--)
{ {
/* add new character to buffer, increment mdi */ /* add new character to buffer, increment mdi */
in[mdi++] = *inBuf++; in[mdi++] = *inBuf++;
/* transform if necessary */ /* transform if necessary */
if(mdi == 0x40) if (mdi == 0x40)
{ {
for(unsigned int j = 0, jj = 0; j < 16; j++, jj += 4) for (unsigned int j = 0, jj = 0; j < 16; j++, jj += 4)
{ {
input[j] = (((UINT4)in[jj + 3]) << 24) | (((UINT4)in[jj + 2]) << 16) input[j] = (((UINT4)in[jj + 3]) << 24) | (((UINT4)in[jj + 2]) << 16)
| (((UINT4)in[jj + 1]) << 8) | ((UINT4)in[jj]); | (((UINT4)in[jj + 1]) << 8) | ((UINT4)in[jj]);
@ -97,7 +95,7 @@ MD5::Update(const unsigned char *inBuf, uint32_t inLen)
} }
void void
MD5::Final(uint8_t *digest) MD5::Final(uint8_t* digest)
{ {
UINT4 input[16]; UINT4 input[16];
int mdi; int mdi;
@ -115,7 +113,7 @@ MD5::Final(uint8_t *digest)
this->Update(PADDING, padLen); this->Update(PADDING, padLen);
/* append length in bits and transform */ /* append length in bits and transform */
for(unsigned int j = 0, jj = 0; j < 14; j++, jj += 4) for (unsigned int j = 0, jj = 0; j < 14; j++, jj += 4)
{ {
input[j] = (((UINT4)in[jj + 3]) << 24) | (((UINT4)in[jj + 2]) << 16) input[j] = (((UINT4)in[jj + 3]) << 24) | (((UINT4)in[jj + 2]) << 16)
| (((UINT4)in[jj + 1]) << 8) | ((UINT4)in[jj]); | (((UINT4)in[jj + 1]) << 8) | ((UINT4)in[jj]);
@ -123,9 +121,9 @@ MD5::Final(uint8_t *digest)
Transform(this->buf, input); Transform(this->buf, input);
/* store buffer in digest */ /* store buffer in digest */
for(unsigned int j = 0, jj = 0; j < 4; j++, jj += 4) for (unsigned int j = 0, jj = 0; j < 4; j++, jj += 4)
{ {
digest[jj] = (unsigned char)(this->buf[j] & 0xFF); digest[jj] = (unsigned char)(this->buf[j] & 0xFF);
digest[jj + 1] = (unsigned char)((this->buf[j] >> 8) & 0xFF); digest[jj + 1] = (unsigned char)((this->buf[j] >> 8) & 0xFF);
digest[jj + 2] = (unsigned char)((this->buf[j] >> 16) & 0xFF); digest[jj + 2] = (unsigned char)((this->buf[j] >> 16) & 0xFF);
digest[jj + 3] = (unsigned char)((this->buf[j] >> 24) & 0xFF); digest[jj + 3] = (unsigned char)((this->buf[j] >> 24) & 0xFF);
@ -135,7 +133,7 @@ MD5::Final(uint8_t *digest)
/* Basic MD5 step. Transform buf based on in. /* Basic MD5 step. Transform buf based on in.
*/ */
void void
Transform(UINT4 *buf, UINT4 *in) Transform(UINT4* buf, UINT4* in)
{ {
UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];

@ -23,7 +23,7 @@ namespace abyss
llarp_time_t m_LastActive; llarp_time_t m_LastActive;
llarp_time_t m_ReadTimeout; llarp_time_t m_ReadTimeout;
bool m_Bad; bool m_Bad;
std::unique_ptr< json::IParser > m_BodyParser; std::unique_ptr<json::IParser> m_BodyParser;
nlohmann::json m_Request; nlohmann::json m_Request;
enum HTTPState enum HTTPState
@ -42,16 +42,16 @@ namespace abyss
ConnImpl(BaseReqHandler* p, llarp_tcp_conn* c, llarp_time_t readtimeout) ConnImpl(BaseReqHandler* p, llarp_tcp_conn* c, llarp_time_t readtimeout)
: _conn(c), _parent(p) : _conn(c), _parent(p)
{ {
handler = nullptr; handler = nullptr;
m_LastActive = p->now(); m_LastActive = p->now();
m_ReadTimeout = readtimeout; m_ReadTimeout = readtimeout;
// set up tcp members // set up tcp members
_conn->user = this; _conn->user = this;
_conn->read = &ConnImpl::OnRead; _conn->read = &ConnImpl::OnRead;
_conn->tick = &ConnImpl::OnTick; _conn->tick = &ConnImpl::OnTick;
_conn->closed = &ConnImpl::OnClosed; _conn->closed = &ConnImpl::OnClosed;
m_Bad = false; m_Bad = false;
m_State = eReadHTTPMethodLine; m_State = eReadHTTPMethodLine;
} }
~ConnImpl() = default; ~ConnImpl() = default;
@ -60,14 +60,14 @@ namespace abyss
FeedLine(std::string& line) FeedLine(std::string& line)
{ {
bool done = false; bool done = false;
switch(m_State) switch (m_State)
{ {
case eReadHTTPMethodLine: case eReadHTTPMethodLine:
return ProcessMethodLine(line); return ProcessMethodLine(line);
case eReadHTTPHeaders: case eReadHTTPHeaders:
if(!ProcessHeaderLine(line, done)) if (!ProcessHeaderLine(line, done))
return false; return false;
if(done) if (done)
m_State = eReadHTTPBody; m_State = eReadHTTPBody;
return true; return true;
default: default:
@ -79,15 +79,15 @@ namespace abyss
ProcessMethodLine(string_view line) ProcessMethodLine(string_view line)
{ {
auto idx = line.find_first_of(' '); auto idx = line.find_first_of(' ');
if(idx == string_view::npos) if (idx == string_view::npos)
return false; return false;
Header.Method = std::string(line.substr(0, idx)); Header.Method = std::string(line.substr(0, idx));
line = line.substr(idx + 1); line = line.substr(idx + 1);
idx = line.find_first_of(' '); idx = line.find_first_of(' ');
if(idx == string_view::npos) if (idx == string_view::npos)
return false; return false;
Header.Path = std::string(line.substr(0, idx)); Header.Path = std::string(line.substr(0, idx));
m_State = eReadHTTPHeaders; m_State = eReadHTTPHeaders;
return true; return true;
} }
@ -95,119 +95,110 @@ namespace abyss
ShouldProcessHeader(const string_view& name) const ShouldProcessHeader(const string_view& name) const
{ {
// TODO: header whitelist // TODO: header whitelist
return name == string_view("content-type") return name == string_view("content-type") || name == string_view("content-length")
|| name == string_view("content-length")
|| name == string_view("host"); || name == string_view("host");
} }
bool bool
WriteResponseSimple(int code, const std::string& msg, WriteResponseSimple(
const char* contentType, const char* content) int code, const std::string& msg, const char* contentType, const char* content)
{ {
char buf[512] = {0}; char buf[512] = {0};
size_t contentLength = strlen(content); size_t contentLength = strlen(content);
int sz = snprintf(buf, sizeof(buf), int sz = snprintf(
"HTTP/1.0 %d %s\r\nContent-Type: " buf,
"%s\r\nContent-Length: %zu\r\n\r\n", sizeof(buf),
code, msg.c_str(), contentType, contentLength); "HTTP/1.0 %d %s\r\nContent-Type: "
if(sz <= 0) "%s\r\nContent-Length: %zu\r\n\r\n",
code,
msg.c_str(),
contentType,
contentLength);
if (sz <= 0)
return false; return false;
if(!llarp_tcp_conn_async_write(_conn, llarp_buffer_t(buf, sz))) if (!llarp_tcp_conn_async_write(_conn, llarp_buffer_t(buf, sz)))
return false; return false;
m_State = eWriteHTTPBody; m_State = eWriteHTTPBody;
return llarp_tcp_conn_async_write( return llarp_tcp_conn_async_write(_conn, llarp_buffer_t(content, contentLength));
_conn, llarp_buffer_t(content, contentLength));
} }
bool bool
FeedBody(const char* buf, size_t sz) FeedBody(const char* buf, size_t sz)
{ {
if(Header.Method != "POST") if (Header.Method != "POST")
{ {
return WriteResponseSimple(405, "Method Not Allowed", "text/plain", return WriteResponseSimple(405, "Method Not Allowed", "text/plain", "nope");
"nope");
} }
{ {
auto itr = Header.Headers.find("content-type"); auto itr = Header.Headers.find("content-type");
if(itr == Header.Headers.end()) if (itr == Header.Headers.end())
{ {
return WriteResponseSimple(415, "Unsupported Media Type", return WriteResponseSimple(
"text/plain", 415, "Unsupported Media Type", "text/plain", "no content type provided");
"no content type provided");
} }
else if(itr->second != string_view("application/json")) else if (itr->second != string_view("application/json"))
{ {
return WriteResponseSimple(415, "Unsupported Media Type", return WriteResponseSimple(
"text/plain", 415, "Unsupported Media Type", "text/plain", "this does not look like jsonrpc 2.0");
"this does not look like jsonrpc 2.0");
} }
} }
// initialize body parser // initialize body parser
if(m_BodyParser == nullptr) if (m_BodyParser == nullptr)
{ {
auto itr = Header.Headers.find("content-length"); auto itr = Header.Headers.find("content-length");
if(itr == Header.Headers.end()) if (itr == Header.Headers.end())
{ {
return WriteResponseSimple(400, "Bad Request", "text/plain", return WriteResponseSimple(400, "Bad Request", "text/plain", "no content length");
"no content length");
} }
ssize_t contentLength = std::stoll(itr->second); ssize_t contentLength = std::stoll(itr->second);
if(contentLength <= 0) if (contentLength <= 0)
{ {
return WriteResponseSimple(400, "Bad Request", "text/plain", return WriteResponseSimple(400, "Bad Request", "text/plain", "bad content length");
"bad content length");
} }
else else
{ {
m_BodyParser.reset(json::MakeParser(contentLength)); m_BodyParser.reset(json::MakeParser(contentLength));
} }
itr = Header.Headers.find("host"); itr = Header.Headers.find("host");
if(itr == Header.Headers.end()) if (itr == Header.Headers.end())
{ {
return WriteResponseSimple(400, "Bad Request", "text/plain", return WriteResponseSimple(400, "Bad Request", "text/plain", "no host header provided");
"no host header provided");
} }
if(not handler->ValidateHost(itr->second)) if (not handler->ValidateHost(itr->second))
{ {
return WriteResponseSimple(400, "Bad Request", "text/plain", return WriteResponseSimple(400, "Bad Request", "text/plain", "invalid host header");
"invalid host header");
} }
} }
if(!m_BodyParser->FeedData(buf, sz)) if (!m_BodyParser->FeedData(buf, sz))
{ {
return WriteResponseSimple(400, "Bad Request", "text/plain", return WriteResponseSimple(400, "Bad Request", "text/plain", "invalid body size");
"invalid body size");
} }
switch(m_BodyParser->Parse(m_Request)) switch (m_BodyParser->Parse(m_Request))
{ {
case json::IParser::eNeedData: case json::IParser::eNeedData:
return true; return true;
case json::IParser::eParseError: case json::IParser::eParseError:
return WriteResponseSimple(400, "Bad Request", "text/plain", return WriteResponseSimple(400, "Bad Request", "text/plain", "bad json object");
"bad json object");
case json::IParser::eDone: case json::IParser::eDone:
if(m_Request.is_object() && m_Request.count("params") if (m_Request.is_object() && m_Request.count("params") && m_Request.count("method")
&& m_Request.count("method") && m_Request.count("id") && m_Request.count("id") && m_Request["id"].is_string()
&& m_Request["id"].is_string() && m_Request["method"].is_string() && m_Request["method"].is_string() && m_Request["params"].is_object())
&& m_Request["params"].is_object())
{ {
nlohmann::json response; nlohmann::json response;
response["jsonrpc"] = "2.0"; response["jsonrpc"] = "2.0";
response["id"] = m_Request["id"].get< std::string >(); response["id"] = m_Request["id"].get<std::string>();
auto value = handler->HandleJSONRPC( auto value = handler->HandleJSONRPC(
m_Request["method"].get< std::string >(), m_Request["method"].get<std::string>(), m_Request["params"]);
m_Request["params"]);
if(!value.is_null()) if (!value.is_null())
response["result"] = std::move(value); response["result"] = std::move(value);
return WriteResponseJSON(response); return WriteResponseJSON(response);
} }
return WriteResponseSimple(500, "internal error", "text/plain", return WriteResponseSimple(500, "internal error", "text/plain", "nope");
"nope");
default: default:
return false; return false;
} }
@ -217,43 +208,42 @@ namespace abyss
WriteResponseJSON(const nlohmann::json& response) WriteResponseJSON(const nlohmann::json& response)
{ {
std::string responseStr = response.dump(); std::string responseStr = response.dump();
return WriteResponseSimple(200, "OK", "application/json", return WriteResponseSimple(200, "OK", "application/json", responseStr.c_str());
responseStr.c_str());
} }
bool bool
ProcessRead(const char* buf, size_t sz) ProcessRead(const char* buf, size_t sz)
{ {
llarp::LogDebug("http read ", sz, " bytes"); llarp::LogDebug("http read ", sz, " bytes");
if(m_Bad) if (m_Bad)
{ {
return false; return false;
} }
if(!sz) if (!sz)
return true; return true;
bool done = false; bool done = false;
m_LastActive = _parent->now(); m_LastActive = _parent->now();
if(m_State < eReadHTTPBody) if (m_State < eReadHTTPBody)
{ {
const char* end = strstr(buf, "\r\n"); const char* end = strstr(buf, "\r\n");
while(end) while (end)
{ {
string_view line(buf, end - buf); string_view line(buf, end - buf);
switch(m_State) switch (m_State)
{ {
case eReadHTTPMethodLine: case eReadHTTPMethodLine:
if(!ProcessMethodLine(line)) if (!ProcessMethodLine(line))
return false; return false;
sz -= line.size() + (2 * sizeof(char)); sz -= line.size() + (2 * sizeof(char));
break; break;
case eReadHTTPHeaders: case eReadHTTPHeaders:
if(!ProcessHeaderLine(line, done)) if (!ProcessHeaderLine(line, done))
return false; return false;
sz -= line.size() + (2 * sizeof(char)); sz -= line.size() + (2 * sizeof(char));
if(done) if (done)
m_State = eReadHTTPBody; m_State = eReadHTTPBody;
break; break;
default: default:
@ -263,7 +253,7 @@ namespace abyss
end = strstr(buf, "\r\n"); end = strstr(buf, "\r\n");
} }
} }
if(m_State == eReadHTTPBody) if (m_State == eReadHTTPBody)
return FeedBody(buf, sz); return FeedBody(buf, sz);
return false; return false;
} }
@ -271,8 +261,8 @@ namespace abyss
static void static void
OnRead(llarp_tcp_conn* conn, const llarp_buffer_t& buf) OnRead(llarp_tcp_conn* conn, const llarp_buffer_t& buf)
{ {
ConnImpl* self = static_cast< ConnImpl* >(conn->user); ConnImpl* self = static_cast<ConnImpl*>(conn->user);
if(!self->ProcessRead((const char*)buf.base, buf.sz)) if (!self->ProcessRead((const char*)buf.base, buf.sz))
self->MarkBad(); self->MarkBad();
} }
@ -280,22 +270,22 @@ namespace abyss
OnClosed(llarp_tcp_conn* conn) OnClosed(llarp_tcp_conn* conn)
{ {
llarp::LogDebug("connection closed"); llarp::LogDebug("connection closed");
ConnImpl* self = static_cast< ConnImpl* >(conn->user); ConnImpl* self = static_cast<ConnImpl*>(conn->user);
self->_conn = nullptr; self->_conn = nullptr;
self->m_State = eCloseMe; self->m_State = eCloseMe;
} }
static void static void
OnTick(llarp_tcp_conn* conn) OnTick(llarp_tcp_conn* conn)
{ {
ConnImpl* self = static_cast< ConnImpl* >(conn->user); ConnImpl* self = static_cast<ConnImpl*>(conn->user);
self->Tick(); self->Tick();
} }
void void
Tick() Tick()
{ {
if(m_Bad) if (m_Bad)
Close(); Close();
} }
@ -309,14 +299,13 @@ namespace abyss
bool bool
ShouldClose(llarp_time_t now) const ShouldClose(llarp_time_t now) const
{ {
return now - m_LastActive > m_ReadTimeout || m_Bad return now - m_LastActive > m_ReadTimeout || m_Bad || m_State == eCloseMe;
|| m_State == eCloseMe;
} }
void void
Close() Close()
{ {
if(_conn) if (_conn)
{ {
llarp_tcp_conn_close(_conn); llarp_tcp_conn_close(_conn);
_conn = nullptr; _conn = nullptr;
@ -340,21 +329,19 @@ namespace abyss
return m_Impl->ShouldClose(now); return m_Impl->ShouldClose(now);
} }
BaseReqHandler::BaseReqHandler(llarp_time_t reqtimeout) BaseReqHandler::BaseReqHandler(llarp_time_t reqtimeout) : m_ReqTimeout(reqtimeout)
: m_ReqTimeout(reqtimeout)
{ {
m_acceptor.accepted = &BaseReqHandler::OnAccept; m_acceptor.accepted = &BaseReqHandler::OnAccept;
m_acceptor.user = this; m_acceptor.user = this;
m_acceptor.tick = &OnTick; m_acceptor.tick = &OnTick;
m_acceptor.closed = nullptr; m_acceptor.closed = nullptr;
} }
bool bool
BaseReqHandler::ServeAsync(llarp_ev_loop_ptr loop, BaseReqHandler::ServeAsync(
std::shared_ptr< llarp::Logic > logic, llarp_ev_loop_ptr loop, std::shared_ptr<llarp::Logic> logic, const sockaddr* bindaddr)
const sockaddr* bindaddr)
{ {
m_loop = loop; m_loop = loop;
m_Logic = logic; m_Logic = logic;
return llarp_tcp_serve(m_loop.get(), &m_acceptor, bindaddr); return llarp_tcp_serve(m_loop.get(), &m_acceptor, bindaddr);
} }
@ -362,7 +349,7 @@ namespace abyss
void void
BaseReqHandler::OnTick(llarp_tcp_acceptor* tcp) BaseReqHandler::OnTick(llarp_tcp_acceptor* tcp)
{ {
BaseReqHandler* self = static_cast< BaseReqHandler* >(tcp->user); BaseReqHandler* self = static_cast<BaseReqHandler*>(tcp->user);
self->Tick(); self->Tick();
} }
@ -371,10 +358,10 @@ namespace abyss
BaseReqHandler::Tick() BaseReqHandler::Tick()
{ {
auto _now = now(); auto _now = now();
auto itr = m_Conns.begin(); auto itr = m_Conns.begin();
while(itr != m_Conns.end()) while (itr != m_Conns.end())
{ {
if((*itr)->ShouldClose(_now)) if ((*itr)->ShouldClose(_now))
itr = m_Conns.erase(itr); itr = m_Conns.erase(itr);
else else
++itr; ++itr;
@ -394,10 +381,10 @@ namespace abyss
void void
BaseReqHandler::OnAccept(llarp_tcp_acceptor* acceptor, llarp_tcp_conn* conn) BaseReqHandler::OnAccept(llarp_tcp_acceptor* acceptor, llarp_tcp_conn* conn)
{ {
BaseReqHandler* self = static_cast< BaseReqHandler* >(acceptor->user); BaseReqHandler* self = static_cast<BaseReqHandler*>(acceptor->user);
ConnImpl* connimpl = new ConnImpl(self, conn, self->m_ReqTimeout); ConnImpl* connimpl = new ConnImpl(self, conn, self->m_ReqTimeout);
IRPCHandler* rpcHandler = self->CreateHandler(connimpl); IRPCHandler* rpcHandler = self->CreateHandler(connimpl);
if(rpcHandler == nullptr) if (rpcHandler == nullptr)
{ {
connimpl->Close(); connimpl->Close();
delete connimpl; delete connimpl;

@ -38,8 +38,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
typedef struct NetlinkList typedef struct NetlinkList
{ {
struct NetlinkList *m_next; struct NetlinkList* m_next;
struct nlmsghdr *m_data; struct nlmsghdr* m_data;
unsigned int m_size; unsigned int m_size;
} NetlinkList; } NetlinkList;
@ -47,7 +47,7 @@ static int
netlink_socket(void) netlink_socket(void)
{ {
int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if(l_socket < 0) if (l_socket < 0)
{ {
return -1; return -1;
} }
@ -55,7 +55,7 @@ netlink_socket(void)
struct sockaddr_nl l_addr; struct sockaddr_nl l_addr;
memset(&l_addr, 0, sizeof(l_addr)); memset(&l_addr, 0, sizeof(l_addr));
l_addr.nl_family = AF_NETLINK; l_addr.nl_family = AF_NETLINK;
if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0) if (bind(l_socket, (struct sockaddr*)&l_addr, sizeof(l_addr)) < 0)
{ {
close(l_socket); close(l_socket);
return -1; return -1;
@ -75,48 +75,53 @@ netlink_send(int p_socket, int p_request)
memset(&l_data, 0, sizeof(l_data)); memset(&l_data, 0, sizeof(l_data));
l_data.m_hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); l_data.m_hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
l_data.m_hdr.nlmsg_type = p_request; l_data.m_hdr.nlmsg_type = p_request;
l_data.m_hdr.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; l_data.m_hdr.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
l_data.m_hdr.nlmsg_pid = 0; l_data.m_hdr.nlmsg_pid = 0;
l_data.m_hdr.nlmsg_seq = p_socket; l_data.m_hdr.nlmsg_seq = p_socket;
l_data.m_msg.rtgen_family = AF_UNSPEC; l_data.m_msg.rtgen_family = AF_UNSPEC;
struct sockaddr_nl l_addr; struct sockaddr_nl l_addr;
memset(&l_addr, 0, sizeof(l_addr)); memset(&l_addr, 0, sizeof(l_addr));
l_addr.nl_family = AF_NETLINK; l_addr.nl_family = AF_NETLINK;
return (sendto(p_socket, &l_data.m_hdr, l_data.m_hdr.nlmsg_len, 0, return (sendto(
(struct sockaddr *)&l_addr, sizeof(l_addr))); p_socket,
&l_data.m_hdr,
l_data.m_hdr.nlmsg_len,
0,
(struct sockaddr*)&l_addr,
sizeof(l_addr)));
} }
static int static int
netlink_recv(int p_socket, void *p_buffer, size_t p_len) netlink_recv(int p_socket, void* p_buffer, size_t p_len)
{ {
struct msghdr l_msg; struct msghdr l_msg;
struct iovec l_iov = {p_buffer, p_len}; struct iovec l_iov = {p_buffer, p_len};
struct sockaddr_nl l_addr; struct sockaddr_nl l_addr;
for(;;) for (;;)
{ {
l_msg.msg_name = (void *)&l_addr; l_msg.msg_name = (void*)&l_addr;
l_msg.msg_namelen = sizeof(l_addr); l_msg.msg_namelen = sizeof(l_addr);
l_msg.msg_iov = &l_iov; l_msg.msg_iov = &l_iov;
l_msg.msg_iovlen = 1; l_msg.msg_iovlen = 1;
l_msg.msg_control = NULL; l_msg.msg_control = NULL;
l_msg.msg_controllen = 0; l_msg.msg_controllen = 0;
l_msg.msg_flags = 0; l_msg.msg_flags = 0;
int l_result = recvmsg(p_socket, &l_msg, 0); int l_result = recvmsg(p_socket, &l_msg, 0);
if(l_result < 0) if (l_result < 0)
{ {
if(errno == EINTR) if (errno == EINTR)
{ {
continue; continue;
} }
return -2; return -2;
} }
if(l_msg.msg_flags & MSG_TRUNC) if (l_msg.msg_flags & MSG_TRUNC)
{ // buffer was too small { // buffer was too small
return -1; return -1;
} }
@ -124,49 +129,47 @@ netlink_recv(int p_socket, void *p_buffer, size_t p_len)
} }
} }
static struct nlmsghdr * static struct nlmsghdr*
getNetlinkResponse(int p_socket, int *p_size, int *p_done) getNetlinkResponse(int p_socket, int* p_size, int* p_done)
{ {
size_t l_size = 4096; size_t l_size = 4096;
void *l_buffer = NULL; void* l_buffer = NULL;
for(;;) for (;;)
{ {
free(l_buffer); free(l_buffer);
l_buffer = malloc(l_size); l_buffer = malloc(l_size);
if(l_buffer == NULL) if (l_buffer == NULL)
{ {
return NULL; return NULL;
} }
int l_read = netlink_recv(p_socket, l_buffer, l_size); int l_read = netlink_recv(p_socket, l_buffer, l_size);
*p_size = l_read; *p_size = l_read;
if(l_read == -2) if (l_read == -2)
{ {
free(l_buffer); free(l_buffer);
return NULL; return NULL;
} }
if(l_read >= 0) if (l_read >= 0)
{ {
pid_t l_pid = getpid(); pid_t l_pid = getpid();
struct nlmsghdr *l_hdr; struct nlmsghdr* l_hdr;
for(l_hdr = (struct nlmsghdr *)l_buffer; for (l_hdr = (struct nlmsghdr*)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read);
NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr*)NLMSG_NEXT(l_hdr, l_read))
l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read))
{ {
if((pid_t)l_hdr->nlmsg_pid != l_pid if ((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
|| (int)l_hdr->nlmsg_seq != p_socket)
{ {
continue; continue;
} }
if(l_hdr->nlmsg_type == NLMSG_DONE) if (l_hdr->nlmsg_type == NLMSG_DONE)
{ {
*p_done = 1; *p_done = 1;
break; break;
} }
if(l_hdr->nlmsg_type == NLMSG_ERROR) if (l_hdr->nlmsg_type == NLMSG_ERROR)
{ {
free(l_buffer); free(l_buffer);
return NULL; return NULL;
@ -179,11 +182,11 @@ getNetlinkResponse(int p_socket, int *p_size, int *p_done)
} }
} }
static NetlinkList * static NetlinkList*
newListItem(struct nlmsghdr *p_data, unsigned int p_size) newListItem(struct nlmsghdr* p_data, unsigned int p_size)
{ {
NetlinkList *l_item = malloc(sizeof(NetlinkList)); NetlinkList* l_item = malloc(sizeof(NetlinkList));
if(l_item == NULL) if (l_item == NULL)
{ {
return NULL; return NULL;
} }
@ -195,46 +198,46 @@ newListItem(struct nlmsghdr *p_data, unsigned int p_size)
} }
static void static void
freeResultList(NetlinkList *p_list) freeResultList(NetlinkList* p_list)
{ {
NetlinkList *l_cur; NetlinkList* l_cur;
while(p_list) while (p_list)
{ {
l_cur = p_list; l_cur = p_list;
p_list = p_list->m_next; p_list = p_list->m_next;
free(l_cur->m_data); free(l_cur->m_data);
free(l_cur); free(l_cur);
} }
} }
static NetlinkList * static NetlinkList*
getResultList(int p_socket, int p_request) getResultList(int p_socket, int p_request)
{ {
if(netlink_send(p_socket, p_request) < 0) if (netlink_send(p_socket, p_request) < 0)
{ {
return NULL; return NULL;
} }
NetlinkList *l_list = NULL; NetlinkList* l_list = NULL;
NetlinkList *l_end = NULL; NetlinkList* l_end = NULL;
int l_size; int l_size;
int l_done = 0; int l_done = 0;
while(!l_done) while (!l_done)
{ {
struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done); struct nlmsghdr* l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done);
if(!l_hdr) if (!l_hdr)
{ // error { // error
freeResultList(l_list); freeResultList(l_list);
return NULL; return NULL;
} }
NetlinkList *l_item = newListItem(l_hdr, l_size); NetlinkList* l_item = newListItem(l_hdr, l_size);
if(!l_item) if (!l_item)
{ {
freeResultList(l_list); freeResultList(l_list);
return NULL; return NULL;
} }
if(!l_list) if (!l_list)
{ {
l_list = l_item; l_list = l_item;
} }
@ -256,36 +259,34 @@ maxSize(size_t a, size_t b)
static size_t static size_t
calcAddrLen(sa_family_t p_family, int p_dataSize) calcAddrLen(sa_family_t p_family, int p_dataSize)
{ {
switch(p_family) switch (p_family)
{ {
case AF_INET: case AF_INET:
return sizeof(struct sockaddr_in); return sizeof(struct sockaddr_in);
case AF_INET6: case AF_INET6:
return sizeof(struct sockaddr_in6); return sizeof(struct sockaddr_in6);
case AF_PACKET: case AF_PACKET:
return maxSize(sizeof(struct sockaddr_ll), return maxSize(
offsetof(struct sockaddr_ll, sll_addr) + p_dataSize); sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize);
default: default:
return maxSize(sizeof(struct sockaddr), return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize);
offsetof(struct sockaddr, sa_data) + p_dataSize);
} }
} }
static void static void
makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, makeSockaddr(sa_family_t p_family, struct sockaddr* p_dest, void* p_data, size_t p_size)
size_t p_size)
{ {
switch(p_family) switch (p_family)
{ {
case AF_INET: case AF_INET:
memcpy(&((struct sockaddr_in *)p_dest)->sin_addr, p_data, p_size); memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size);
break; break;
case AF_INET6: case AF_INET6:
memcpy(&((struct sockaddr_in6 *)p_dest)->sin6_addr, p_data, p_size); memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size);
break; break;
case AF_PACKET: case AF_PACKET:
memcpy(((struct sockaddr_ll *)p_dest)->sll_addr, p_data, p_size); memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size);
((struct sockaddr_ll *)p_dest)->sll_halen = p_size; ((struct sockaddr_ll*)p_dest)->sll_halen = p_size;
break; break;
default: default:
memcpy(p_dest->sa_data, p_data, p_size); memcpy(p_dest->sa_data, p_data, p_size);
@ -295,16 +296,16 @@ makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data,
} }
static void static void
addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry) addToEnd(struct ifaddrs** p_resultList, struct ifaddrs* p_entry)
{ {
if(!*p_resultList) if (!*p_resultList)
{ {
*p_resultList = p_entry; *p_resultList = p_entry;
} }
else else
{ {
struct ifaddrs *l_cur = *p_resultList; struct ifaddrs* l_cur = *p_resultList;
while(l_cur->ifa_next) while (l_cur->ifa_next)
{ {
l_cur = l_cur->ifa_next; l_cur = l_cur->ifa_next;
} }
@ -313,23 +314,22 @@ addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry)
} }
static int static int
interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList) interpretLink(struct nlmsghdr* p_hdr, struct ifaddrs** p_resultList)
{ {
struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr); struct ifinfomsg* l_info = (struct ifinfomsg*)NLMSG_DATA(p_hdr);
size_t l_nameSize = 0; size_t l_nameSize = 0;
size_t l_addrSize = 0; size_t l_addrSize = 0;
size_t l_dataSize = 0; size_t l_dataSize = 0;
size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg)); size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
struct rtattr *l_rta; struct rtattr* l_rta;
for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); for (l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
l_rta = RTA_NEXT(l_rta, l_rtaSize))
{ {
void *l_rtaData = RTA_DATA(l_rta); void* l_rtaData = RTA_DATA(l_rta);
(void)l_rtaData; (void)l_rtaData;
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
switch(l_rta->rta_type) switch (l_rta->rta_type)
{ {
case IFLA_ADDRESS: case IFLA_ADDRESS:
case IFLA_BROADCAST: case IFLA_BROADCAST:
@ -346,19 +346,19 @@ interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList)
} }
} }
struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + sizeof(int) struct ifaddrs* l_entry =
+ l_nameSize + l_addrSize + l_dataSize); malloc(sizeof(struct ifaddrs) + sizeof(int) + l_nameSize + l_addrSize + l_dataSize);
if(l_entry == NULL) if (l_entry == NULL)
{ {
return -1; return -1;
} }
memset(l_entry, 0, sizeof(struct ifaddrs)); memset(l_entry, 0, sizeof(struct ifaddrs));
l_entry->ifa_name = ""; l_entry->ifa_name = "";
char *l_index = ((char *)l_entry) + sizeof(struct ifaddrs); char* l_index = ((char*)l_entry) + sizeof(struct ifaddrs);
char *l_name = l_index + sizeof(int); char* l_name = l_index + sizeof(int);
char *l_addr = l_name + l_nameSize; char* l_addr = l_name + l_nameSize;
char *l_data = l_addr + l_addrSize; char* l_data = l_addr + l_addrSize;
// save the interface index so we can look it up when handling the addresses. // save the interface index so we can look it up when handling the addresses.
memcpy(l_index, &l_info->ifi_index, sizeof(int)); memcpy(l_index, &l_info->ifi_index, sizeof(int));
@ -366,28 +366,26 @@ interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList)
l_entry->ifa_flags = l_info->ifi_flags; l_entry->ifa_flags = l_info->ifi_flags;
l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg)); l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); for (l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
l_rta = RTA_NEXT(l_rta, l_rtaSize))
{ {
void *l_rtaData = RTA_DATA(l_rta); void* l_rtaData = RTA_DATA(l_rta);
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
switch(l_rta->rta_type) switch (l_rta->rta_type)
{ {
case IFLA_ADDRESS: case IFLA_ADDRESS:
case IFLA_BROADCAST: case IFLA_BROADCAST:
{ {
size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize); size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize);
makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, makeSockaddr(AF_PACKET, (struct sockaddr*)l_addr, l_rtaData, l_rtaDataSize);
l_rtaDataSize); ((struct sockaddr_ll*)l_addr)->sll_ifindex = l_info->ifi_index;
((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index; ((struct sockaddr_ll*)l_addr)->sll_hatype = l_info->ifi_type;
((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type; if (l_rta->rta_type == IFLA_ADDRESS)
if(l_rta->rta_type == IFLA_ADDRESS)
{ {
l_entry->ifa_addr = (struct sockaddr *)l_addr; l_entry->ifa_addr = (struct sockaddr*)l_addr;
} }
else else
{ {
l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; l_entry->ifa_broadaddr = (struct sockaddr*)l_addr;
} }
l_addr += NLMSG_ALIGN(l_addrLen); l_addr += NLMSG_ALIGN(l_addrLen);
break; break;
@ -395,7 +393,7 @@ interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList)
case IFLA_IFNAME: case IFLA_IFNAME:
strncpy(l_name, l_rtaData, l_rtaDataSize); strncpy(l_name, l_rtaData, l_rtaDataSize);
l_name[l_rtaDataSize] = '\0'; l_name[l_rtaDataSize] = '\0';
l_entry->ifa_name = l_name; l_entry->ifa_name = l_name;
break; break;
case IFLA_STATS: case IFLA_STATS:
memcpy(l_data, l_rtaData, l_rtaDataSize); memcpy(l_data, l_rtaData, l_rtaDataSize);
@ -410,17 +408,17 @@ interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList)
return 0; return 0;
} }
static struct ifaddrs * static struct ifaddrs*
findInterface(int p_index, struct ifaddrs **p_links, int p_numLinks) findInterface(int p_index, struct ifaddrs** p_links, int p_numLinks)
{ {
int l_num = 0; int l_num = 0;
struct ifaddrs *l_cur = *p_links; struct ifaddrs* l_cur = *p_links;
while(l_cur && l_num < p_numLinks) while (l_cur && l_num < p_numLinks)
{ {
char *l_indexPtr = ((char *)l_cur) + sizeof(struct ifaddrs); char* l_indexPtr = ((char*)l_cur) + sizeof(struct ifaddrs);
int l_index; int l_index;
memcpy(&l_index, l_indexPtr, sizeof(int)); memcpy(&l_index, l_indexPtr, sizeof(int));
if(l_index == p_index) if (l_index == p_index)
{ {
return l_cur; return l_cur;
} }
@ -432,14 +430,12 @@ findInterface(int p_index, struct ifaddrs **p_links, int p_numLinks)
} }
static int static int
interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, interpretAddr(struct nlmsghdr* p_hdr, struct ifaddrs** p_resultList, int p_numLinks)
int p_numLinks)
{ {
struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr); struct ifaddrmsg* l_info = (struct ifaddrmsg*)NLMSG_DATA(p_hdr);
struct ifaddrs *l_interface = struct ifaddrs* l_interface = findInterface(l_info->ifa_index, p_resultList, p_numLinks);
findInterface(l_info->ifa_index, p_resultList, p_numLinks);
if(l_info->ifa_family == AF_PACKET) if (l_info->ifa_family == AF_PACKET)
{ {
return 0; return 0;
} }
@ -450,28 +446,24 @@ interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList,
int l_addedNetmask = 0; int l_addedNetmask = 0;
size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
struct rtattr *l_rta; struct rtattr* l_rta;
for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); for (l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
l_rta = RTA_NEXT(l_rta, l_rtaSize))
{ {
void *l_rtaData = RTA_DATA(l_rta); void* l_rtaData = RTA_DATA(l_rta);
(void)l_rtaData; (void)l_rtaData;
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
switch(l_rta->rta_type) switch (l_rta->rta_type)
{ {
case IFA_ADDRESS: case IFA_ADDRESS:
case IFA_LOCAL: case IFA_LOCAL:
if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) if ((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask)
&& !l_addedNetmask)
{ // make room for netmask { // make room for netmask
l_addrSize += l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
l_addedNetmask = 1; l_addedNetmask = 1;
} }
case IFA_BROADCAST: case IFA_BROADCAST:
l_addrSize += l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
break; break;
case IFA_LABEL: case IFA_LABEL:
l_nameSize += NLMSG_ALIGN(l_rtaSize + 1); l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
@ -481,71 +473,68 @@ interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList,
} }
} }
struct ifaddrs *l_entry = struct ifaddrs* l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize);
malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize); if (l_entry == NULL)
if(l_entry == NULL)
{ {
return -1; return -1;
} }
memset(l_entry, 0, sizeof(struct ifaddrs)); memset(l_entry, 0, sizeof(struct ifaddrs));
l_entry->ifa_name = (l_interface ? l_interface->ifa_name : ""); l_entry->ifa_name = (l_interface ? l_interface->ifa_name : "");
char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs); char* l_name = ((char*)l_entry) + sizeof(struct ifaddrs);
char *l_addr = l_name + l_nameSize; char* l_addr = l_name + l_nameSize;
l_entry->ifa_flags = l_info->ifa_flags; l_entry->ifa_flags = l_info->ifa_flags;
if(l_interface) if (l_interface)
{ {
l_entry->ifa_flags |= l_interface->ifa_flags; l_entry->ifa_flags |= l_interface->ifa_flags;
} }
l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); for (l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
l_rta = RTA_NEXT(l_rta, l_rtaSize))
{ {
void *l_rtaData = RTA_DATA(l_rta); void* l_rtaData = RTA_DATA(l_rta);
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
switch(l_rta->rta_type) switch (l_rta->rta_type)
{ {
case IFA_ADDRESS: case IFA_ADDRESS:
case IFA_BROADCAST: case IFA_BROADCAST:
case IFA_LOCAL: case IFA_LOCAL:
{ {
size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize); size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize);
makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, makeSockaddr(l_info->ifa_family, (struct sockaddr*)l_addr, l_rtaData, l_rtaDataSize);
l_rtaDataSize); if (l_info->ifa_family == AF_INET6)
if(l_info->ifa_family == AF_INET6)
{ {
if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) if (IN6_IS_ADDR_LINKLOCAL((struct in6_addr*)l_rtaData)
|| IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData)) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr*)l_rtaData))
{ {
((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index; ((struct sockaddr_in6*)l_addr)->sin6_scope_id = l_info->ifa_index;
} }
} }
if(l_rta->rta_type == IFA_ADDRESS) if (l_rta->rta_type == IFA_ADDRESS)
{ // apparently in a point-to-point network IFA_ADDRESS contains the { // apparently in a point-to-point network IFA_ADDRESS contains the
// dest address and IFA_LOCAL contains the local address // dest address and IFA_LOCAL contains the local address
if(l_entry->ifa_addr) if (l_entry->ifa_addr)
{ {
l_entry->ifa_dstaddr = (struct sockaddr *)l_addr; l_entry->ifa_dstaddr = (struct sockaddr*)l_addr;
} }
else else
{ {
l_entry->ifa_addr = (struct sockaddr *)l_addr; l_entry->ifa_addr = (struct sockaddr*)l_addr;
} }
} }
else if(l_rta->rta_type == IFA_LOCAL) else if (l_rta->rta_type == IFA_LOCAL)
{ {
if(l_entry->ifa_addr) if (l_entry->ifa_addr)
{ {
l_entry->ifa_dstaddr = l_entry->ifa_addr; l_entry->ifa_dstaddr = l_entry->ifa_addr;
} }
l_entry->ifa_addr = (struct sockaddr *)l_addr; l_entry->ifa_addr = (struct sockaddr*)l_addr;
} }
else else
{ {
l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; l_entry->ifa_broadaddr = (struct sockaddr*)l_addr;
} }
l_addr += NLMSG_ALIGN(l_addrLen); l_addr += NLMSG_ALIGN(l_addrLen);
break; break;
@ -553,35 +542,31 @@ interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList,
case IFA_LABEL: case IFA_LABEL:
strncpy(l_name, l_rtaData, l_rtaDataSize); strncpy(l_name, l_rtaData, l_rtaDataSize);
l_name[l_rtaDataSize] = '\0'; l_name[l_rtaDataSize] = '\0';
l_entry->ifa_name = l_name; l_entry->ifa_name = l_name;
break; break;
default: default:
break; break;
} }
} }
if(l_entry->ifa_addr if (l_entry->ifa_addr
&& (l_entry->ifa_addr->sa_family == AF_INET && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6))
|| l_entry->ifa_addr->sa_family == AF_INET6))
{ {
unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128); unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128);
unsigned l_prefix = unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen);
(l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix
: l_info->ifa_prefixlen);
char l_mask[16] = {0}; char l_mask[16] = {0};
unsigned i; unsigned i;
for(i = 0; i < (l_prefix / 8); ++i) for (i = 0; i < (l_prefix / 8); ++i)
{ {
l_mask[i] = 0xff; l_mask[i] = 0xff;
} }
if(l_prefix % 8) if (l_prefix % 8)
{ {
l_mask[i] = 0xff << (8 - (l_prefix % 8)); l_mask[i] = 0xff << (8 - (l_prefix % 8));
} }
makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr*)l_addr, l_mask, l_maxPrefix / 8);
l_mask, l_maxPrefix / 8); l_entry->ifa_netmask = (struct sockaddr*)l_addr;
l_entry->ifa_netmask = (struct sockaddr *)l_addr;
} }
addToEnd(p_resultList, l_entry); addToEnd(p_resultList, l_entry);
@ -589,31 +574,30 @@ interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList,
} }
static int static int
interpretLinks(int p_socket, NetlinkList *p_netlinkList, interpretLinks(int p_socket, NetlinkList* p_netlinkList, struct ifaddrs** p_resultList)
struct ifaddrs **p_resultList)
{ {
int l_numLinks = 0; int l_numLinks = 0;
pid_t l_pid = getpid(); pid_t l_pid = getpid();
for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) for (; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
{ {
unsigned int l_nlsize = p_netlinkList->m_size; unsigned int l_nlsize = p_netlinkList->m_size;
struct nlmsghdr *l_hdr; struct nlmsghdr* l_hdr;
for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); for (l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize);
l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
{ {
if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) if ((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
{ {
continue; continue;
} }
if(l_hdr->nlmsg_type == NLMSG_DONE) if (l_hdr->nlmsg_type == NLMSG_DONE)
{ {
break; break;
} }
if(l_hdr->nlmsg_type == RTM_NEWLINK) if (l_hdr->nlmsg_type == RTM_NEWLINK)
{ {
if(interpretLink(l_hdr, p_resultList) == -1) if (interpretLink(l_hdr, p_resultList) == -1)
{ {
return -1; return -1;
} }
@ -625,30 +609,30 @@ interpretLinks(int p_socket, NetlinkList *p_netlinkList,
} }
static int static int
interpretAddrs(int p_socket, NetlinkList *p_netlinkList, interpretAddrs(
struct ifaddrs **p_resultList, int p_numLinks) int p_socket, NetlinkList* p_netlinkList, struct ifaddrs** p_resultList, int p_numLinks)
{ {
pid_t l_pid = getpid(); pid_t l_pid = getpid();
for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) for (; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
{ {
unsigned int l_nlsize = p_netlinkList->m_size; unsigned int l_nlsize = p_netlinkList->m_size;
struct nlmsghdr *l_hdr; struct nlmsghdr* l_hdr;
for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); for (l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize);
l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
{ {
if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) if ((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
{ {
continue; continue;
} }
if(l_hdr->nlmsg_type == NLMSG_DONE) if (l_hdr->nlmsg_type == NLMSG_DONE)
{ {
break; break;
} }
if(l_hdr->nlmsg_type == RTM_NEWADDR) if (l_hdr->nlmsg_type == RTM_NEWADDR)
{ {
if(interpretAddr(l_hdr, p_resultList, p_numLinks) == -1) if (interpretAddr(l_hdr, p_resultList, p_numLinks) == -1)
{ {
return -1; return -1;
} }
@ -659,39 +643,38 @@ interpretAddrs(int p_socket, NetlinkList *p_netlinkList,
} }
int int
getifaddrs(struct ifaddrs **ifap) getifaddrs(struct ifaddrs** ifap)
{ {
if(!ifap) if (!ifap)
{ {
return -1; return -1;
} }
*ifap = NULL; *ifap = NULL;
int l_socket = netlink_socket(); int l_socket = netlink_socket();
if(l_socket < 0) if (l_socket < 0)
{ {
return -1; return -1;
} }
NetlinkList *l_linkResults = getResultList(l_socket, RTM_GETLINK); NetlinkList* l_linkResults = getResultList(l_socket, RTM_GETLINK);
if(!l_linkResults) if (!l_linkResults)
{ {
close(l_socket); close(l_socket);
return -1; return -1;
} }
NetlinkList *l_addrResults = getResultList(l_socket, RTM_GETADDR); NetlinkList* l_addrResults = getResultList(l_socket, RTM_GETADDR);
if(!l_addrResults) if (!l_addrResults)
{ {
close(l_socket); close(l_socket);
freeResultList(l_linkResults); freeResultList(l_linkResults);
return -1; return -1;
} }
int l_result = 0; int l_result = 0;
int l_numLinks = interpretLinks(l_socket, l_linkResults, ifap); int l_numLinks = interpretLinks(l_socket, l_linkResults, ifap);
if(l_numLinks == -1 if (l_numLinks == -1 || interpretAddrs(l_socket, l_addrResults, ifap, l_numLinks) == -1)
|| interpretAddrs(l_socket, l_addrResults, ifap, l_numLinks) == -1)
{ {
l_result = -1; l_result = -1;
} }
@ -703,13 +686,13 @@ getifaddrs(struct ifaddrs **ifap)
} }
void void
freeifaddrs(struct ifaddrs *ifa) freeifaddrs(struct ifaddrs* ifa)
{ {
struct ifaddrs *l_cur; struct ifaddrs* l_cur;
while(ifa) while (ifa)
{ {
l_cur = ifa; l_cur = ifa;
ifa = ifa->ifa_next; ifa = ifa->ifa_next;
free(l_cur); free(l_cur);
} }
} }

@ -28,13 +28,13 @@
struct ifaddrs struct ifaddrs
{ {
struct ifaddrs *ifa_next; struct ifaddrs* ifa_next;
char *ifa_name; char* ifa_name;
unsigned int ifa_flags; unsigned int ifa_flags;
struct sockaddr *ifa_addr; struct sockaddr* ifa_addr;
struct sockaddr *ifa_netmask; struct sockaddr* ifa_netmask;
struct sockaddr *ifa_dstaddr; struct sockaddr* ifa_dstaddr;
void *ifa_data; void* ifa_data;
}; };
/* /*
@ -49,9 +49,9 @@ struct ifaddrs
__BEGIN_DECLS __BEGIN_DECLS
extern int extern int
getifaddrs(struct ifaddrs **ifap); getifaddrs(struct ifaddrs** ifap);
extern void extern void
freeifaddrs(struct ifaddrs *ifa); freeifaddrs(struct ifaddrs* ifa);
__END_DECLS __END_DECLS
#endif #endif

@ -14,10 +14,10 @@ namespace llarp
{ {
return bencode_read_list( return bencode_read_list(
[&](llarp_buffer_t* b, bool more) -> bool { [&](llarp_buffer_t* b, bool more) -> bool {
if(more) if (more)
{ {
RouterContact rc; RouterContact rc;
if(not rc.BDecode(b)) if (not rc.BDecode(b))
return false; return false;
emplace(std::move(rc)); emplace(std::move(rc));
} }

@ -6,7 +6,7 @@
namespace llarp namespace llarp
{ {
struct BootstrapList final : public std::set< RouterContact > struct BootstrapList final : public std::set<RouterContact>
{ {
bool bool
BDecode(llarp_buffer_t* buf); BDecode(llarp_buffer_t* buf);

@ -19,7 +19,7 @@
namespace llarp namespace llarp
{ {
const char * const char*
lokinetEnv(string_view suffix) lokinetEnv(string_view suffix)
{ {
std::string env; std::string env;
@ -32,41 +32,41 @@ namespace llarp
std::string std::string
fromEnv(string_view val, string_view envNameSuffix) fromEnv(string_view val, string_view envNameSuffix)
{ {
if(const char *ptr = lokinetEnv(envNameSuffix)) if (const char* ptr = lokinetEnv(envNameSuffix))
return ptr; return ptr;
return {val.begin(), val.end()}; return {val.begin(), val.end()};
} }
int int
fromEnv(const int &val, string_view envNameSuffix) fromEnv(const int& val, string_view envNameSuffix)
{ {
if(const char *ptr = lokinetEnv(envNameSuffix)) if (const char* ptr = lokinetEnv(envNameSuffix))
return std::atoi(ptr); return std::atoi(ptr);
return val; return val;
} }
uint16_t uint16_t
fromEnv(const uint16_t &val, string_view envNameSuffix) fromEnv(const uint16_t& val, string_view envNameSuffix)
{ {
if(const char *ptr = lokinetEnv(envNameSuffix)) if (const char* ptr = lokinetEnv(envNameSuffix))
return std::atoi(ptr); return std::atoi(ptr);
return val; return val;
} }
size_t size_t
fromEnv(const size_t &val, string_view envNameSuffix) fromEnv(const size_t& val, string_view envNameSuffix)
{ {
if(const char *ptr = lokinetEnv(envNameSuffix)) if (const char* ptr = lokinetEnv(envNameSuffix))
return std::atoll(ptr); return std::atoll(ptr);
return val; return val;
} }
nonstd::optional< bool > nonstd::optional<bool>
fromEnv(const nonstd::optional< bool > &val, string_view envNameSuffix) fromEnv(const nonstd::optional<bool>& val, string_view envNameSuffix)
{ {
if(const char *ptr = lokinetEnv(envNameSuffix)) if (const char* ptr = lokinetEnv(envNameSuffix))
return IsTrueValue(ptr); return IsTrueValue(ptr);
return val; return val;
@ -78,14 +78,14 @@ namespace llarp
return std::atoi(val.data()); return std::atoi(val.data());
} }
nonstd::optional< bool > nonstd::optional<bool>
setOptBool(string_view val) setOptBool(string_view val)
{ {
if(IsTrueValue(val)) if (IsTrueValue(val))
{ {
return true; return true;
} }
else if(IsFalseValue(val)) else if (IsFalseValue(val))
{ {
return false; return false;
} }
@ -95,23 +95,23 @@ namespace llarp
void void
RouterConfig::fromSection(string_view key, string_view val) RouterConfig::fromSection(string_view key, string_view val)
{ {
if(key == "job-queue-size") if (key == "job-queue-size")
{ {
auto sval = svtoi(val); auto sval = svtoi(val);
if(sval >= 1024) if (sval >= 1024)
{ {
m_JobQueueSize = sval; m_JobQueueSize = sval;
LogInfo("Set job queue size to ", m_JobQueueSize); LogInfo("Set job queue size to ", m_JobQueueSize);
} }
} }
if(key == "default-protocol") if (key == "default-protocol")
{ {
m_DefaultLinkProto = str(val); m_DefaultLinkProto = str(val);
LogInfo("overriding default link protocol to '", val, "'"); LogInfo("overriding default link protocol to '", val, "'");
} }
if(key == "netid") if (key == "netid")
{ {
if(val.size() <= NetID::size()) if (val.size() <= NetID::size())
{ {
m_netId = str(val); m_netId = str(val);
LogInfo("setting netid to '", val, "'"); LogInfo("setting netid to '", val, "'");
@ -121,77 +121,77 @@ namespace llarp
llarp::LogError("invalid netid '", val, "', is too long"); llarp::LogError("invalid netid '", val, "', is too long");
} }
} }
if(key == "max-connections") if (key == "max-connections")
{ {
auto ival = svtoi(val); auto ival = svtoi(val);
if(ival > 0) if (ival > 0)
{ {
m_maxConnectedRouters = ival; m_maxConnectedRouters = ival;
LogInfo("max connections set to ", m_maxConnectedRouters); LogInfo("max connections set to ", m_maxConnectedRouters);
} }
} }
if(key == "min-connections") if (key == "min-connections")
{ {
auto ival = svtoi(val); auto ival = svtoi(val);
if(ival > 0) if (ival > 0)
{ {
m_minConnectedRouters = ival; m_minConnectedRouters = ival;
LogInfo("min connections set to ", m_minConnectedRouters); LogInfo("min connections set to ", m_minConnectedRouters);
} }
} }
if(key == "nickname") if (key == "nickname")
{ {
m_nickname = str(val); m_nickname = str(val);
// set logger name here // set logger name here
LogContext::Instance().nodeName = nickname(); LogContext::Instance().nodeName = nickname();
LogInfo("nickname set"); LogInfo("nickname set");
} }
if(key == "encryption-privkey") if (key == "encryption-privkey")
{ {
m_encryptionKeyfile = str(val); m_encryptionKeyfile = str(val);
LogDebug("encryption key set to ", m_encryptionKeyfile); LogDebug("encryption key set to ", m_encryptionKeyfile);
} }
if(key == "contact-file") if (key == "contact-file")
{ {
m_ourRcFile = str(val); m_ourRcFile = str(val);
LogDebug("rc file set to ", m_ourRcFile); LogDebug("rc file set to ", m_ourRcFile);
} }
if(key == "transport-privkey") if (key == "transport-privkey")
{ {
m_transportKeyfile = str(val); m_transportKeyfile = str(val);
LogDebug("transport key set to ", m_transportKeyfile); LogDebug("transport key set to ", m_transportKeyfile);
} }
if((key == "identity-privkey" || key == "ident-privkey")) if ((key == "identity-privkey" || key == "ident-privkey"))
{ {
m_identKeyfile = str(val); m_identKeyfile = str(val);
LogDebug("identity key set to ", m_identKeyfile); LogDebug("identity key set to ", m_identKeyfile);
} }
if(key == "public-address" || key == "public-ip") if (key == "public-address" || key == "public-ip")
{ {
llarp::LogInfo("public ip ", val, " size ", val.size()); llarp::LogInfo("public ip ", val, " size ", val.size());
if(val.size() < 17) if (val.size() < 17)
{ {
// assume IPv4 // assume IPv4
llarp::Addr a(val); llarp::Addr a(val);
llarp::LogInfo("setting public ipv4 ", a); llarp::LogInfo("setting public ipv4 ", a);
m_addrInfo.ip = *a.addr6(); m_addrInfo.ip = *a.addr6();
m_publicOverride = true; m_publicOverride = true;
} }
} }
if(key == "public-port") if (key == "public-port")
{ {
llarp::LogInfo("Setting public port ", val); llarp::LogInfo("Setting public port ", val);
int p = svtoi(val); int p = svtoi(val);
// Not needed to flip upside-down - this is done in llarp::Addr(const // Not needed to flip upside-down - this is done in llarp::Addr(const
// AddressInfo&) // AddressInfo&)
m_ip4addr.sin_port = p; m_ip4addr.sin_port = p;
m_addrInfo.port = p; m_addrInfo.port = p;
m_publicOverride = true; m_publicOverride = true;
} }
if(key == "worker-threads" || key == "threads") if (key == "worker-threads" || key == "threads")
{ {
m_workerThreads = svtoi(val); m_workerThreads = svtoi(val);
if(m_workerThreads <= 0) if (m_workerThreads <= 0)
{ {
LogWarn("worker threads invalid value: '", val, "' defaulting to 1"); LogWarn("worker threads invalid value: '", val, "' defaulting to 1");
m_workerThreads = 1; m_workerThreads = 1;
@ -201,10 +201,10 @@ namespace llarp
LogDebug("set to use ", m_workerThreads, " worker threads"); LogDebug("set to use ", m_workerThreads, " worker threads");
} }
} }
if(key == "net-threads") if (key == "net-threads")
{ {
m_numNetThreads = svtoi(val); m_numNetThreads = svtoi(val);
if(m_numNetThreads <= 0) if (m_numNetThreads <= 0)
{ {
LogWarn("net threads invalid value: '", val, "' defaulting to 1"); LogWarn("net threads invalid value: '", val, "' defaulting to 1");
m_numNetThreads = 1; m_numNetThreads = 1;
@ -214,7 +214,7 @@ namespace llarp
LogDebug("set to use ", m_numNetThreads, " net threads"); LogDebug("set to use ", m_numNetThreads, " net threads");
} }
} }
if(key == "block-bogons") if (key == "block-bogons")
{ {
m_blockBogons = setOptBool(val); m_blockBogons = setOptBool(val);
} }
@ -223,16 +223,16 @@ namespace llarp
void void
NetworkConfig::fromSection(string_view key, string_view val) NetworkConfig::fromSection(string_view key, string_view val)
{ {
if(key == "profiling") if (key == "profiling")
{ {
m_enableProfiling = setOptBool(val); m_enableProfiling = setOptBool(val);
} }
else if(key == "profiles") else if (key == "profiles")
{ {
m_routerProfilesFile = str(val); m_routerProfilesFile = str(val);
llarp::LogInfo("setting profiles to ", routerProfilesFile()); llarp::LogInfo("setting profiles to ", routerProfilesFile());
} }
else if(key == "strict-connect") else if (key == "strict-connect")
{ {
m_strictConnect = str(val); m_strictConnect = str(val);
} }
@ -245,7 +245,7 @@ namespace llarp
void void
NetdbConfig::fromSection(string_view key, string_view val) NetdbConfig::fromSection(string_view key, string_view val)
{ {
if(key == "dir") if (key == "dir")
{ {
m_nodedbDir = str(val); m_nodedbDir = str(val);
} }
@ -254,12 +254,12 @@ namespace llarp
void void
DnsConfig::fromSection(string_view key, string_view val) DnsConfig::fromSection(string_view key, string_view val)
{ {
if(key == "upstream") if (key == "upstream")
{ {
llarp::LogInfo("add upstream resolver ", val); llarp::LogInfo("add upstream resolver ", val);
netConfig.emplace("upstream-dns", str(val)); // str() for gcc 5 compat netConfig.emplace("upstream-dns", str(val)); // str() for gcc 5 compat
} }
if(key == "bind") if (key == "bind")
{ {
llarp::LogInfo("set local dns to ", val); llarp::LogInfo("set local dns to ", val);
netConfig.emplace("local-dns", str(val)); // str() for gcc 5 compat netConfig.emplace("local-dns", str(val)); // str() for gcc 5 compat
@ -271,13 +271,13 @@ namespace llarp
{ {
uint16_t proto = 0; uint16_t proto = 0;
std::unordered_set< std::string > parsed_opts; std::unordered_set<std::string> parsed_opts;
std::string::size_type idx; std::string::size_type idx;
static constexpr char delimiter = ','; static constexpr char delimiter = ',';
do do
{ {
idx = val.find_first_of(delimiter); idx = val.find_first_of(delimiter);
if(idx != string_view::npos) if (idx != string_view::npos)
{ {
parsed_opts.emplace(TrimWhitespace(val.substr(0, idx))); parsed_opts.emplace(TrimWhitespace(val.substr(0, idx)));
val.remove_prefix(idx + 1); val.remove_prefix(idx + 1);
@ -286,17 +286,17 @@ namespace llarp
{ {
parsed_opts.emplace(TrimWhitespace(val)); parsed_opts.emplace(TrimWhitespace(val));
} }
} while(idx != string_view::npos); } while (idx != string_view::npos);
std::unordered_set< std::string > opts; std::unordered_set<std::string> opts;
/// for each option /// for each option
for(const auto &item : parsed_opts) for (const auto& item : parsed_opts)
{ {
/// see if it's a number /// see if it's a number
auto port = std::atoi(item.c_str()); auto port = std::atoi(item.c_str());
if(port > 0) if (port > 0)
{ {
/// set port /// set port
if(proto == 0) if (proto == 0)
{ {
proto = port; proto = port;
} }
@ -307,10 +307,10 @@ namespace llarp
} }
} }
if(key == "*") if (key == "*")
{ {
m_OutboundLink = std::make_tuple( m_OutboundLink =
"*", AF_INET, fromEnv(proto, "OUTBOUND_PORT"), std::move(opts)); std::make_tuple("*", AF_INET, fromEnv(proto, "OUTBOUND_PORT"), std::move(opts));
} }
else else
{ {
@ -334,7 +334,7 @@ namespace llarp
void void
SystemConfig::fromSection(string_view key, string_view val) SystemConfig::fromSection(string_view key, string_view val)
{ {
if(key == "pidfile") if (key == "pidfile")
{ {
pidfile = str(val); pidfile = str(val);
} }
@ -343,15 +343,15 @@ namespace llarp
void void
ApiConfig::fromSection(string_view key, string_view val) ApiConfig::fromSection(string_view key, string_view val)
{ {
if(key == "enabled") if (key == "enabled")
{ {
m_enableRPCServer = IsTrueValue(val); m_enableRPCServer = IsTrueValue(val);
} }
if(key == "bind") if (key == "bind")
{ {
m_rpcBindAddr = str(val); m_rpcBindAddr = str(val);
} }
if(key == "authkey") if (key == "authkey")
{ {
// TODO: add pubkey to whitelist // TODO: add pubkey to whitelist
} }
@ -360,24 +360,24 @@ namespace llarp
void void
LokidConfig::fromSection(string_view key, string_view val) LokidConfig::fromSection(string_view key, string_view val)
{ {
if(key == "service-node-seed") if (key == "service-node-seed")
{ {
usingSNSeed = true; usingSNSeed = true;
ident_keyfile = std::string{val}; ident_keyfile = std::string{val};
} }
if(key == "enabled") if (key == "enabled")
{ {
whitelistRouters = IsTrueValue(val); whitelistRouters = IsTrueValue(val);
} }
if(key == "jsonrpc" || key == "addr") if (key == "jsonrpc" || key == "addr")
{ {
lokidRPCAddr = str(val); lokidRPCAddr = str(val);
} }
if(key == "username") if (key == "username")
{ {
lokidRPCUser = str(val); lokidRPCUser = str(val);
} }
if(key == "password") if (key == "password")
{ {
lokidRPCPassword = str(val); lokidRPCPassword = str(val);
} }
@ -386,7 +386,7 @@ namespace llarp
void void
BootstrapConfig::fromSection(string_view key, string_view val) BootstrapConfig::fromSection(string_view key, string_view val)
{ {
if(key == "add-node") if (key == "add-node")
{ {
routers.emplace_back(val.begin(), val.end()); routers.emplace_back(val.begin(), val.end());
} }
@ -395,71 +395,71 @@ namespace llarp
void void
LoggingConfig::fromSection(string_view key, string_view val) LoggingConfig::fromSection(string_view key, string_view val)
{ {
if(key == "type" && val == "syslog") if (key == "type" && val == "syslog")
{ {
// TODO(despair): write event log syslog class // TODO(despair): write event log syslog class
#if defined(_WIN32) #if defined(_WIN32)
LogError("syslog not supported on win32"); LogError("syslog not supported on win32");
#else #else
LogInfo("Switching to syslog"); LogInfo("Switching to syslog");
LogContext::Instance().logStream = std::make_unique< SysLogStream >(); LogContext::Instance().logStream = std::make_unique<SysLogStream>();
#endif #endif
} }
if(key == "level") if (key == "level")
{ {
const auto maybe = LogLevelFromString(str(val)); const auto maybe = LogLevelFromString(str(val));
if(not maybe.has_value()) if (not maybe.has_value())
{ {
LogError("bad log level: ", val); LogError("bad log level: ", val);
return; return;
} }
const LogLevel lvl = maybe.value(); const LogLevel lvl = maybe.value();
LogContext::Instance().runtimeLevel = lvl; LogContext::Instance().runtimeLevel = lvl;
LogInfo("Log level set to ", LogLevelToName(lvl)); LogInfo("Log level set to ", LogLevelToName(lvl));
} }
if(key == "type" && val == "json") if (key == "type" && val == "json")
{ {
m_LogJSON = true; m_LogJSON = true;
} }
if(key == "file") if (key == "file")
{ {
LogInfo("open log file: ", val); LogInfo("open log file: ", val);
std::string fname{val}; std::string fname{val};
FILE *const logfile = ::fopen(fname.c_str(), "a"); FILE* const logfile = ::fopen(fname.c_str(), "a");
if(logfile) if (logfile)
{ {
m_LogFile = logfile; m_LogFile = logfile;
LogInfo("will log to file ", val); LogInfo("will log to file ", val);
} }
else if(errno) else if (errno)
{ {
LogError("could not open log file at '", val, "': ", strerror(errno)); LogError("could not open log file at '", val, "': ", strerror(errno));
errno = 0; errno = 0;
} }
else else
{ {
LogError("failed to open log file at '", val, LogError(
"' for an unknown reason, bailing tf out kbai"); "failed to open log file at '", val, "' for an unknown reason, bailing tf out kbai");
::abort(); ::abort();
} }
} }
} }
template < typename Section, typename Config > template <typename Section, typename Config>
Section Section
find_section(Config &c, const std::string &name) find_section(Config& c, const std::string& name)
{ {
Section ret; Section ret;
auto visitor = [&ret](const ConfigParser::Section_t &section) -> bool { auto visitor = [&ret](const ConfigParser::Section_t& section) -> bool {
for(const auto &sec : section) for (const auto& sec : section)
{ {
ret.fromSection(sec.first, sec.second); ret.fromSection(sec.first, sec.second);
} }
return true; return true;
}; };
if(c.VisitSection(name.c_str(), visitor)) if (c.VisitSection(name.c_str(), visitor))
{ {
return ret; return ret;
} }
@ -468,10 +468,10 @@ namespace llarp
} }
bool bool
Config::Load(const char *fname) Config::Load(const char* fname)
{ {
ConfigParser parser; ConfigParser parser;
if(!parser.LoadFile(fname)) if (!parser.LoadFile(fname))
{ {
return false; return false;
} }
@ -483,7 +483,7 @@ namespace llarp
Config::LoadFromStr(string_view str) Config::LoadFromStr(string_view str)
{ {
ConfigParser parser; ConfigParser parser;
if(!parser.LoadFromStr(str)) if (!parser.LoadFromStr(str))
{ {
return false; return false;
} }
@ -492,22 +492,22 @@ namespace llarp
} }
bool bool
Config::parse(const ConfigParser &parser) Config::parse(const ConfigParser& parser)
{ {
if(Lokinet_INIT()) if (Lokinet_INIT())
return false; return false;
router = find_section< RouterConfig >(parser, "router"); router = find_section<RouterConfig>(parser, "router");
network = find_section< NetworkConfig >(parser, "network"); network = find_section<NetworkConfig>(parser, "network");
connect = find_section< ConnectConfig >(parser, "connect"); connect = find_section<ConnectConfig>(parser, "connect");
netdb = find_section< NetdbConfig >(parser, "netdb"); netdb = find_section<NetdbConfig>(parser, "netdb");
dns = find_section< DnsConfig >(parser, "dns"); dns = find_section<DnsConfig>(parser, "dns");
links = find_section< LinksConfig >(parser, "bind"); links = find_section<LinksConfig>(parser, "bind");
services = find_section< ServicesConfig >(parser, "services"); services = find_section<ServicesConfig>(parser, "services");
system = find_section< SystemConfig >(parser, "system"); system = find_section<SystemConfig>(parser, "system");
api = find_section< ApiConfig >(parser, "api"); api = find_section<ApiConfig>(parser, "api");
lokid = find_section< LokidConfig >(parser, "lokid"); lokid = find_section<LokidConfig>(parser, "lokid");
bootstrap = find_section< BootstrapConfig >(parser, "bootstrap"); bootstrap = find_section<BootstrapConfig>(parser, "bootstrap");
logging = find_section< LoggingConfig >(parser, "logging"); logging = find_section<LoggingConfig>(parser, "logging");
return true; return true;
} }
@ -533,24 +533,23 @@ namespace llarp
/// fname should be a relative path (from CWD) or absolute path to the config /// fname should be a relative path (from CWD) or absolute path to the config
/// file /// file
extern "C" bool extern "C" bool
llarp_ensure_config(const char *fname, const char *basedir, bool overwrite, llarp_ensure_config(const char* fname, const char* basedir, bool overwrite, bool asRouter)
bool asRouter)
{ {
if(Lokinet_INIT()) if (Lokinet_INIT())
return false; return false;
std::error_code ec; std::error_code ec;
if(fs::exists(fname, ec) && !overwrite) if (fs::exists(fname, ec) && !overwrite)
{ {
return true; return true;
} }
if(ec) if (ec)
{ {
llarp::LogError(ec); llarp::LogError(ec);
return false; return false;
} }
std::string basepath; std::string basepath;
if(basedir) if (basedir)
{ {
basepath = basedir; basepath = basedir;
#ifndef _WIN32 #ifndef _WIN32
@ -563,14 +562,14 @@ llarp_ensure_config(const char *fname, const char *basedir, bool overwrite,
llarp::LogInfo("Attempting to create config file ", fname); llarp::LogInfo("Attempting to create config file ", fname);
// abort if config already exists // abort if config already exists
if(!asRouter) if (!asRouter)
{ {
if(fs::exists(fname, ec) && !overwrite) if (fs::exists(fname, ec) && !overwrite)
{ {
llarp::LogError(fname, " currently exists, please use -f to overwrite"); llarp::LogError(fname, " currently exists, please use -f to overwrite");
return true; return true;
} }
if(ec) if (ec)
{ {
llarp::LogError(ec); llarp::LogError(ec);
return false; return false;
@ -578,16 +577,15 @@ llarp_ensure_config(const char *fname, const char *basedir, bool overwrite,
} }
// write fname ini // write fname ini
auto optional_f = auto optional_f = llarp::util::OpenFileStream<std::ofstream>(fname, std::ios::binary);
llarp::util::OpenFileStream< std::ofstream >(fname, std::ios::binary); if (!optional_f || !optional_f.value().is_open())
if(!optional_f || !optional_f.value().is_open())
{ {
llarp::LogError("failed to open ", fname, " for writing"); llarp::LogError("failed to open ", fname, " for writing");
return false; return false;
} }
auto &f = optional_f.value(); auto& f = optional_f.value();
llarp_generic_ensure_config(f, basepath, asRouter); llarp_generic_ensure_config(f, basepath, asRouter);
if(asRouter) if (asRouter)
{ {
llarp_ensure_router_config(f, basepath); llarp_ensure_router_config(f, basepath);
} }
@ -600,8 +598,7 @@ llarp_ensure_config(const char *fname, const char *basedir, bool overwrite,
} }
void void
llarp_generic_ensure_config(std::ofstream &f, std::string basepath, llarp_generic_ensure_config(std::ofstream& f, std::string basepath, bool isRouter)
bool isRouter)
{ {
f << "# this configuration was auto generated with 'sane' defaults\n"; f << "# this configuration was auto generated with 'sane' defaults\n";
f << "# change these values as desired\n"; f << "# change these values as desired\n";
@ -618,8 +615,7 @@ llarp_generic_ensure_config(std::ofstream &f, std::string basepath,
f << "# encryption key for onion routing\n"; f << "# encryption key for onion routing\n";
f << "encryption-privkey=" << basepath << "encryption.private\n"; f << "encryption-privkey=" << basepath << "encryption.private\n";
f << std::endl; f << std::endl;
f << "# uncomment following line to set router nickname to 'lokinet'" f << "# uncomment following line to set router nickname to 'lokinet'" << std::endl;
<< std::endl;
f << "#nickname=lokinet\n"; f << "#nickname=lokinet\n";
const auto limits = isRouter ? llarp::limits::snode : llarp::limits::client; const auto limits = isRouter ? llarp::limits::snode : llarp::limits::client;
@ -695,7 +691,7 @@ llarp_generic_ensure_config(std::ofstream &f, std::string basepath,
} }
void void
llarp_ensure_router_config(std::ofstream &f, std::string basepath) llarp_ensure_router_config(std::ofstream& f, std::string basepath)
{ {
f << "# lokid settings (disabled by default)\n"; f << "# lokid settings (disabled by default)\n";
f << "[lokid]\n"; f << "[lokid]\n";
@ -720,7 +716,7 @@ llarp_ensure_router_config(std::ofstream &f, std::string basepath)
f << "[bind]\n"; f << "[bind]\n";
// get ifname // get ifname
std::string ifname; std::string ifname;
if(llarp::GetBestNetIF(ifname, AF_INET)) if (llarp::GetBestNetIF(ifname, AF_INET))
{ {
f << ifname << "=1090\n"; f << ifname << "=1090\n";
} }
@ -734,19 +730,18 @@ llarp_ensure_router_config(std::ofstream &f, std::string basepath)
} }
bool bool
llarp_ensure_client_config(std::ofstream &f, std::string basepath) llarp_ensure_client_config(std::ofstream& f, std::string basepath)
{ {
// write snapp-example.ini // write snapp-example.ini
const std::string snappExample_fpath = basepath + "snapp-example.ini"; const std::string snappExample_fpath = basepath + "snapp-example.ini";
{ {
auto stream = llarp::util::OpenFileStream< std::ofstream >( auto stream = llarp::util::OpenFileStream<std::ofstream>(snappExample_fpath, std::ios::binary);
snappExample_fpath, std::ios::binary); if (!stream)
if(!stream)
{ {
return false; return false;
} }
auto &example_f = stream.value(); auto& example_f = stream.value();
if(example_f.is_open()) if (example_f.is_open())
{ {
// pick ip // pick ip
// don't revert me // don't revert me

@ -29,8 +29,8 @@ namespace llarp
fromEnv(const uint16_t& val, string_view envNameSuffix); fromEnv(const uint16_t& val, string_view envNameSuffix);
size_t size_t
fromEnv(const size_t& val, string_view envNameSuffix); fromEnv(const size_t& val, string_view envNameSuffix);
nonstd::optional< bool > nonstd::optional<bool>
fromEnv(const nonstd::optional< bool >& val, string_view envNameSuffix); fromEnv(const nonstd::optional<bool>& val, string_view envNameSuffix);
class RouterConfig class RouterConfig
{ {
@ -55,7 +55,7 @@ namespace llarp
// long term identity key // long term identity key
std::string m_identKeyfile = "identity.key"; std::string m_identKeyfile = "identity.key";
nonstd::optional< bool > m_blockBogons; nonstd::optional<bool> m_blockBogons;
bool m_publicOverride = false; bool m_publicOverride = false;
struct sockaddr_in m_ip4addr; struct sockaddr_in m_ip4addr;
@ -95,10 +95,10 @@ namespace llarp
class NetworkConfig class NetworkConfig
{ {
public: public:
using NetConfig = std::unordered_multimap< std::string, std::string >; using NetConfig = std::unordered_multimap<std::string, std::string>;
public: public:
nonstd::optional< bool > m_enableProfiling; nonstd::optional<bool> m_enableProfiling;
std::string m_routerProfilesFile = "profiles.dat"; std::string m_routerProfilesFile = "profiles.dat";
std::string m_strictConnect; std::string m_strictConnect;
NetConfig m_netConfig; NetConfig m_netConfig;
@ -131,7 +131,7 @@ namespace llarp
struct DnsConfig struct DnsConfig
{ {
std::unordered_multimap< std::string, std::string > netConfig; std::unordered_multimap<std::string, std::string> netConfig;
void void
fromSection(string_view key, string_view val); fromSection(string_view key, string_view val);
@ -140,14 +140,14 @@ namespace llarp
class LinksConfig class LinksConfig
{ {
public: public:
static constexpr int Interface = 0; static constexpr int Interface = 0;
static constexpr int AddressFamily = 1; static constexpr int AddressFamily = 1;
static constexpr int Port = 2; static constexpr int Port = 2;
static constexpr int Options = 3; static constexpr int Options = 3;
using ServerOptions = std::unordered_set< std::string >; using ServerOptions = std::unordered_set<std::string>;
using LinkInfo = std::tuple< std::string, int, uint16_t, ServerOptions >; using LinkInfo = std::tuple<std::string, int, uint16_t, ServerOptions>;
using Links = std::vector< LinkInfo >; using Links = std::vector<LinkInfo>;
public: public:
LinkInfo m_OutboundLink; LinkInfo m_OutboundLink;
@ -166,7 +166,7 @@ namespace llarp
struct ConnectConfig struct ConnectConfig
{ {
std::vector< std::string > routers; std::vector<std::string> routers;
void void
fromSection(string_view key, string_view val); fromSection(string_view key, string_view val);
@ -174,7 +174,7 @@ namespace llarp
struct ServicesConfig struct ServicesConfig
{ {
std::vector< std::pair< std::string, std::string > > services; std::vector<std::pair<std::string, std::string>> services;
void void
fromSection(string_view key, string_view val); fromSection(string_view key, string_view val);
}; };
@ -190,7 +190,7 @@ namespace llarp
class ApiConfig class ApiConfig
{ {
public: public:
bool m_enableRPCServer = false; bool m_enableRPCServer = false;
std::string m_rpcBindAddr = "127.0.0.1:1190"; std::string m_rpcBindAddr = "127.0.0.1:1190";
public: public:
@ -205,9 +205,9 @@ namespace llarp
struct LokidConfig struct LokidConfig
{ {
bool usingSNSeed = false; bool usingSNSeed = false;
bool whitelistRouters = false; bool whitelistRouters = false;
fs::path ident_keyfile = "identity.key"; fs::path ident_keyfile = "identity.key";
std::string lokidRPCAddr = "127.0.0.1:22023"; std::string lokidRPCAddr = "127.0.0.1:22023";
std::string lokidRPCUser; std::string lokidRPCUser;
std::string lokidRPCPassword; std::string lokidRPCPassword;
@ -218,14 +218,14 @@ namespace llarp
struct BootstrapConfig struct BootstrapConfig
{ {
std::vector< std::string > routers; std::vector<std::string> routers;
void void
fromSection(string_view key, string_view val); fromSection(string_view key, string_view val);
}; };
struct LoggingConfig struct LoggingConfig
{ {
bool m_LogJSON = false; bool m_LogJSON = false;
FILE* m_LogFile = stdout; FILE* m_LogFile = stdout;
void void
@ -271,8 +271,7 @@ namespace llarp
} // namespace llarp } // namespace llarp
void void
llarp_generic_ensure_config(std::ofstream& f, std::string basepath, llarp_generic_ensure_config(std::ofstream& f, std::string basepath, bool isRouter);
bool isRouter);
void void
llarp_ensure_router_config(std::ofstream& f, std::string basepath); llarp_ensure_router_config(std::ofstream& f, std::string basepath);

@ -15,12 +15,12 @@ namespace llarp
std::string name{fname}; std::string name{fname};
{ {
std::ifstream f(name, std::ios::in | std::ios::binary); std::ifstream f(name, std::ios::in | std::ios::binary);
if(!f.is_open()) if (!f.is_open())
return false; return false;
f.seekg(0, std::ios::end); f.seekg(0, std::ios::end);
m_Data.resize(f.tellg()); m_Data.resize(f.tellg());
f.seekg(0, std::ios::beg); f.seekg(0, std::ios::beg);
if(m_Data.size() == 0) if (m_Data.size() == 0)
return false; return false;
f.read(m_Data.data(), m_Data.size()); f.read(m_Data.data(), m_Data.size());
} }
@ -47,23 +47,23 @@ namespace llarp
static bool static bool
whitespace(char ch) whitespace(char ch)
{ {
return std::isspace(static_cast< unsigned char >(ch)) != 0; return std::isspace(static_cast<unsigned char>(ch)) != 0;
} }
bool bool
ConfigParser::Parse() ConfigParser::Parse()
{ {
std::list< string_view > lines; std::list<string_view> lines;
{ {
auto itr = m_Data.begin(); auto itr = m_Data.begin();
// split into lines // split into lines
while(itr != m_Data.end()) while (itr != m_Data.end())
{ {
auto beg = itr; auto beg = itr;
while(itr != m_Data.end() && *itr != '\n' && *itr != '\r') while (itr != m_Data.end() && *itr != '\n' && *itr != '\r')
++itr; ++itr;
lines.emplace_back(std::addressof(*beg), std::distance(beg, itr)); lines.emplace_back(std::addressof(*beg), std::distance(beg, itr));
if(itr == m_Data.end()) if (itr == m_Data.end())
break; break;
++itr; ++itr;
} }
@ -71,60 +71,60 @@ namespace llarp
string_view sectName; string_view sectName;
size_t lineno = 0; size_t lineno = 0;
for(const auto& line : lines) for (const auto& line : lines)
{ {
lineno++; lineno++;
string_view realLine; string_view realLine;
auto comment = line.find_first_of(';'); auto comment = line.find_first_of(';');
if(comment == string_view::npos) if (comment == string_view::npos)
comment = line.find_first_of('#'); comment = line.find_first_of('#');
if(comment == string_view::npos) if (comment == string_view::npos)
realLine = line; realLine = line;
else else
realLine = line.substr(0, comment); realLine = line.substr(0, comment);
// blank or commented line? // blank or commented line?
if(realLine.size() == 0) if (realLine.size() == 0)
continue; continue;
// find delimiters // find delimiters
auto sectOpenPos = realLine.find_first_of('['); auto sectOpenPos = realLine.find_first_of('[');
auto sectClosPos = realLine.find_first_of(']'); auto sectClosPos = realLine.find_first_of(']');
auto kvDelim = realLine.find_first_of('='); auto kvDelim = realLine.find_first_of('=');
if(sectOpenPos != string_view::npos && sectClosPos != string_view::npos if (sectOpenPos != string_view::npos && sectClosPos != string_view::npos
&& kvDelim == string_view::npos) && kvDelim == string_view::npos)
{ {
// section header // section header
// clamp whitespaces // clamp whitespaces
++sectOpenPos; ++sectOpenPos;
while(whitespace(realLine[sectOpenPos]) && sectOpenPos != sectClosPos) while (whitespace(realLine[sectOpenPos]) && sectOpenPos != sectClosPos)
++sectOpenPos; ++sectOpenPos;
--sectClosPos; --sectClosPos;
while(whitespace(realLine[sectClosPos]) && sectClosPos != sectOpenPos) while (whitespace(realLine[sectClosPos]) && sectClosPos != sectOpenPos)
--sectClosPos; --sectClosPos;
// set section name // set section name
sectName = realLine.substr(sectOpenPos, sectClosPos); sectName = realLine.substr(sectOpenPos, sectClosPos);
} }
else if(kvDelim != string_view::npos) else if (kvDelim != string_view::npos)
{ {
// key value pair // key value pair
string_view::size_type k_start = 0; string_view::size_type k_start = 0;
string_view::size_type k_end = kvDelim; string_view::size_type k_end = kvDelim;
string_view::size_type v_start = kvDelim + 1; string_view::size_type v_start = kvDelim + 1;
string_view::size_type v_end = realLine.size() - 1; string_view::size_type v_end = realLine.size() - 1;
// clamp whitespaces // clamp whitespaces
while(whitespace(realLine[k_start]) && k_start != kvDelim) while (whitespace(realLine[k_start]) && k_start != kvDelim)
++k_start; ++k_start;
while(whitespace(realLine[k_end - 1]) && k_end != k_start) while (whitespace(realLine[k_end - 1]) && k_end != k_start)
--k_end; --k_end;
while(whitespace(realLine[v_start]) && v_start != v_end) while (whitespace(realLine[v_start]) && v_start != v_end)
++v_start; ++v_start;
while(whitespace(realLine[v_end])) while (whitespace(realLine[v_end]))
--v_end; --v_end;
// sect.k = v // sect.k = v
string_view k = realLine.substr(k_start, k_end - k_start); string_view k = realLine.substr(k_start, k_end - k_start);
string_view v = realLine.substr(v_start, 1 + (v_end - v_start)); string_view v = realLine.substr(v_start, 1 + (v_end - v_start));
if(k.size() == 0 || v.size() == 0) if (k.size() == 0 || v.size() == 0)
{ {
LogError(m_FileName, " invalid line (", lineno, "): '", line, "'"); LogError(m_FileName, " invalid line (", lineno, "): '", line, "'");
return false; return false;
@ -143,20 +143,18 @@ namespace llarp
} }
void void
ConfigParser::IterAll( ConfigParser::IterAll(std::function<void(string_view, const Section_t&)> visit)
std::function< void(string_view, const Section_t&) > visit)
{ {
for(const auto& item : m_Config) for (const auto& item : m_Config)
visit(item.first, item.second); visit(item.first, item.second);
} }
bool bool
ConfigParser::VisitSection( ConfigParser::VisitSection(
const char* name, const char* name, std::function<bool(const Section_t& sect)> visit) const
std::function< bool(const Section_t& sect) > visit) const
{ {
auto itr = m_Config.find(name); auto itr = m_Config.find(name);
if(itr == m_Config.end()) if (itr == m_Config.end())
return false; return false;
return visit(itr->second); return visit(itr->second);
} }

@ -12,8 +12,8 @@ namespace llarp
{ {
struct ConfigParser struct ConfigParser
{ {
using Section_t = std::unordered_multimap< std::string, std::string >; using Section_t = std::unordered_multimap<std::string, std::string>;
using Config_impl_t = std::unordered_map< std::string, Section_t >; using Config_impl_t = std::unordered_map<std::string, Section_t>;
/// clear parser /// clear parser
void void
Clear(); Clear();
@ -32,19 +32,18 @@ namespace llarp
/// iterate all sections and thier values /// iterate all sections and thier values
void void
IterAll(std::function< void(string_view, const Section_t&) > visit); IterAll(std::function<void(string_view, const Section_t&)> visit);
/// visit a section in config read only by name /// visit a section in config read only by name
/// return false if no section or value propagated from visitor /// return false if no section or value propagated from visitor
bool bool
VisitSection(const char* name, VisitSection(const char* name, std::function<bool(const Section_t&)> visit) const;
std::function< bool(const Section_t&) > visit) const;
private: private:
bool bool
Parse(); Parse();
std::vector< char > m_Data; std::vector<char> m_Data;
Config_impl_t m_Config; Config_impl_t m_Config;
std::string m_FileName; std::string m_FileName;
}; };

@ -14,8 +14,8 @@
static size_t static size_t
curl_RecvIdentKey(char* ptr, size_t, size_t nmemb, void* userdata) curl_RecvIdentKey(char* ptr, size_t, size_t nmemb, void* userdata)
{ {
for(size_t idx = 0; idx < nmemb; idx++) for (size_t idx = 0; idx < nmemb; idx++)
static_cast< std::vector< char >* >(userdata)->push_back(ptr[idx]); static_cast<std::vector<char>*>(userdata)->push_back(ptr[idx]);
return nmemb; return nmemb;
} }
@ -28,22 +28,22 @@ namespace llarp
bool bool
KeyManager::initialize(const llarp::Config& config, bool genIfAbsent) KeyManager::initialize(const llarp::Config& config, bool genIfAbsent)
{ {
if(m_initialized) if (m_initialized)
return false; return false;
m_rcPath = config.router.ourRcFile(); m_rcPath = config.router.ourRcFile();
m_idKeyPath = config.router.identKeyfile(); m_idKeyPath = config.router.identKeyfile();
m_encKeyPath = config.router.encryptionKeyfile(); m_encKeyPath = config.router.encryptionKeyfile();
m_transportKeyPath = config.router.transportKeyfile(); m_transportKeyPath = config.router.transportKeyfile();
m_usingLokid = config.lokid.whitelistRouters; m_usingLokid = config.lokid.whitelistRouters;
m_lokidRPCAddr = config.lokid.lokidRPCAddr; m_lokidRPCAddr = config.lokid.lokidRPCAddr;
m_lokidRPCUser = config.lokid.lokidRPCUser; m_lokidRPCUser = config.lokid.lokidRPCUser;
m_lokidRPCPassword = config.lokid.lokidRPCPassword; m_lokidRPCPassword = config.lokid.lokidRPCPassword;
RouterContact rc; RouterContact rc;
bool exists = rc.Read(m_rcPath.c_str()); bool exists = rc.Read(m_rcPath.c_str());
if(not exists and not genIfAbsent) if (not exists and not genIfAbsent)
{ {
LogError("Could not read RouterContact at path ", m_rcPath); LogError("Could not read RouterContact at path ", m_rcPath);
return false; return false;
@ -56,19 +56,21 @@ namespace llarp
// if our RC file can't be verified, assume it is out of date (e.g. uses // if our RC file can't be verified, assume it is out of date (e.g. uses
// older encryption) and needs to be regenerated. before doing so, backup // older encryption) and needs to be regenerated. before doing so, backup
// files that will be overwritten // files that will be overwritten
if(exists and m_needBackup) if (exists and m_needBackup)
{ {
if(!genIfAbsent) if (!genIfAbsent)
{ {
LogError("Our RouterContact ", m_rcPath, " is invalid or out of date"); LogError("Our RouterContact ", m_rcPath, " is invalid or out of date");
return false; return false;
} }
else else
{ {
LogWarn("Our RouterContact ", m_rcPath, LogWarn(
" seems out of date, backing up and regenerating private keys"); "Our RouterContact ",
m_rcPath,
" seems out of date, backing up and regenerating private keys");
if(!backupKeyFilesByMoving()) if (!backupKeyFilesByMoving())
{ {
LogError( LogError(
"Could not mv some key files, please ensure key files" "Could not mv some key files, please ensure key files"
@ -78,19 +80,19 @@ namespace llarp
} }
} }
if(not m_usingLokid) if (not m_usingLokid)
{ {
// load identity key or create if needed // load identity key or create if needed
auto identityKeygen = [](llarp::SecretKey& key) { auto identityKeygen = [](llarp::SecretKey& key) {
// TODO: handle generating from service node seed // TODO: handle generating from service node seed
llarp::CryptoManager::instance()->identity_keygen(key); llarp::CryptoManager::instance()->identity_keygen(key);
}; };
if(not loadOrCreateKey(m_idKeyPath, identityKey, identityKeygen)) if (not loadOrCreateKey(m_idKeyPath, identityKey, identityKeygen))
return false; return false;
} }
else else
{ {
if(not loadIdentityFromLokid()) if (not loadIdentityFromLokid())
return false; return false;
} }
@ -98,7 +100,7 @@ namespace llarp
auto encryptionKeygen = [](llarp::SecretKey& key) { auto encryptionKeygen = [](llarp::SecretKey& key) {
llarp::CryptoManager::instance()->encryption_keygen(key); llarp::CryptoManager::instance()->encryption_keygen(key);
}; };
if(not loadOrCreateKey(m_encKeyPath, encryptionKey, encryptionKeygen)) if (not loadOrCreateKey(m_encKeyPath, encryptionKey, encryptionKeygen))
return false; return false;
// TODO: transport key (currently done in LinkLayer) // TODO: transport key (currently done in LinkLayer)
@ -106,7 +108,7 @@ namespace llarp
key.Zero(); key.Zero();
CryptoManager::instance()->encryption_keygen(key); CryptoManager::instance()->encryption_keygen(key);
}; };
if(not loadOrCreateKey(m_transportKeyPath, transportKey, transportKeygen)) if (not loadOrCreateKey(m_transportKeyPath, transportKey, transportKeygen))
return false; return false;
m_initialized = true; m_initialized = true;
@ -117,13 +119,13 @@ namespace llarp
KeyManager::backupFileByMoving(const std::string& filepath) KeyManager::backupFileByMoving(const std::string& filepath)
{ {
auto findFreeBackupFilename = [](const fs::path& filepath) { auto findFreeBackupFilename = [](const fs::path& filepath) {
for(int i = 0; i < 9; i++) for (int i = 0; i < 9; i++)
{ {
std::string ext("." + std::to_string(i) + ".bak"); std::string ext("." + std::to_string(i) + ".bak");
fs::path newPath = filepath; fs::path newPath = filepath;
newPath += ext; newPath += ext;
if(not fs::exists(newPath)) if (not fs::exists(newPath))
return newPath; return newPath;
} }
return fs::path(); return fs::path();
@ -131,31 +133,29 @@ namespace llarp
std::error_code ec; std::error_code ec;
bool exists = fs::exists(filepath, ec); bool exists = fs::exists(filepath, ec);
if(ec) if (ec)
{ {
LogError("Could not determine status of file ", filepath, ": ", LogError("Could not determine status of file ", filepath, ": ", ec.message());
ec.message());
return false; return false;
} }
if(not exists) if (not exists)
{ {
LogInfo("File ", filepath, " doesn't exist; no backup needed"); LogInfo("File ", filepath, " doesn't exist; no backup needed");
return true; return true;
} }
fs::path newFilepath = findFreeBackupFilename(filepath); fs::path newFilepath = findFreeBackupFilename(filepath);
if(newFilepath.empty()) if (newFilepath.empty())
{ {
LogWarn("Could not find an appropriate backup filename for", filepath); LogWarn("Could not find an appropriate backup filename for", filepath);
return false; return false;
} }
LogInfo("Backing up (moving) key file ", filepath, " to ", newFilepath, LogInfo("Backing up (moving) key file ", filepath, " to ", newFilepath, "...");
"...");
fs::rename(filepath, newFilepath, ec); fs::rename(filepath, newFilepath, ec);
if(ec) if (ec)
{ {
LogError("Failed to move key file ", ec.message()); LogError("Failed to move key file ", ec.message());
return false; return false;
@ -167,12 +167,11 @@ namespace llarp
bool bool
KeyManager::backupKeyFilesByMoving() const KeyManager::backupKeyFilesByMoving() const
{ {
std::vector< std::string > files = {m_rcPath, m_idKeyPath, m_encKeyPath, std::vector<std::string> files = {m_rcPath, m_idKeyPath, m_encKeyPath, m_transportKeyPath};
m_transportKeyPath};
for(auto& filepath : files) for (auto& filepath : files)
{ {
if(not backupFileByMoving(filepath)) if (not backupFileByMoving(filepath))
return false; return false;
} }
@ -181,14 +180,15 @@ namespace llarp
bool bool
KeyManager::loadOrCreateKey( KeyManager::loadOrCreateKey(
const std::string& filepath, llarp::SecretKey& key, const std::string& filepath,
std::function< void(llarp::SecretKey& key) > keygen) llarp::SecretKey& key,
std::function<void(llarp::SecretKey& key)> keygen)
{ {
fs::path path(filepath); fs::path path(filepath);
std::error_code ec; std::error_code ec;
if(!fs::exists(path, ec)) if (!fs::exists(path, ec))
{ {
if(ec) if (ec)
{ {
LogError("Error checking key", filepath, ec.message()); LogError("Error checking key", filepath, ec.message());
return false; return false;
@ -197,7 +197,7 @@ namespace llarp
LogInfo("Generating new key", filepath); LogInfo("Generating new key", filepath);
keygen(key); keygen(key);
if(!key.SaveToFile(filepath.c_str())) if (!key.SaveToFile(filepath.c_str()))
{ {
LogError("Failed to save new key"); LogError("Failed to save new key");
return false; return false;
@ -216,7 +216,7 @@ namespace llarp
return false; return false;
#else #else
CURL* curl = curl_easy_init(); CURL* curl = curl_easy_init();
if(curl) if (curl)
{ {
bool ret = false; bool ret = false;
std::stringstream ss; std::stringstream ss;
@ -230,11 +230,10 @@ namespace llarp
list = curl_slist_append(list, "Content-Type: application/json"); list = curl_slist_append(list, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
nlohmann::json request = {{"id", "0"}, nlohmann::json request = {
{"jsonrpc", "2.0"}, {"id", "0"}, {"jsonrpc", "2.0"}, {"method", "get_service_node_privkey"}};
{"method", "get_service_node_privkey"}}; const auto data = request.dump();
const auto data = request.dump(); std::vector<char> resp;
std::vector< char > resp;
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, data.size()); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, data.size());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str()); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
@ -243,24 +242,23 @@ namespace llarp
resp.clear(); resp.clear();
LogInfo("Getting Identity Keys from lokid..."); LogInfo("Getting Identity Keys from lokid...");
if(curl_easy_perform(curl) == CURLE_OK) if (curl_easy_perform(curl) == CURLE_OK)
{ {
try try
{ {
auto j = nlohmann::json::parse(resp); auto j = nlohmann::json::parse(resp);
if(not j.is_object()) if (not j.is_object())
return false; return false;
const auto itr = j.find("result"); const auto itr = j.find("result");
if(itr == j.end()) if (itr == j.end())
return false; return false;
if(not itr->is_object()) if (not itr->is_object())
return false; return false;
const auto k = const auto k = (*itr)["service_node_ed25519_privkey"].get<std::string>();
(*itr)["service_node_ed25519_privkey"].get< std::string >(); if (k.size() != (identityKey.size() * 2))
if(k.size() != (identityKey.size() * 2))
{ {
if(k.empty()) if (k.empty())
{ {
LogError("lokid gave no identity key"); LogError("lokid gave no identity key");
} }
@ -270,9 +268,9 @@ namespace llarp
} }
return false; return false;
} }
if(not HexDecode(k.c_str(), identityKey.data(), identityKey.size())) if (not HexDecode(k.c_str(), identityKey.data(), identityKey.size()))
return false; return false;
if(CryptoManager::instance()->check_identity_privkey(identityKey)) if (CryptoManager::instance()->check_identity_privkey(identityKey))
{ {
ret = true; ret = true;
} }
@ -281,7 +279,7 @@ namespace llarp
LogError("lokid gave bogus identity key"); LogError("lokid gave bogus identity key");
} }
} }
catch(nlohmann::json::exception& ex) catch (nlohmann::json::exception& ex)
{ {
LogError("Bad response from lokid: ", ex.what()); LogError("Bad response from lokid: ", ex.what());
} }
@ -290,10 +288,9 @@ namespace llarp
{ {
LogError("failed to get identity keys"); LogError("failed to get identity keys");
} }
if(ret) if (ret)
{ {
LogInfo("Got Identity Keys from lokid: ", LogInfo("Got Identity Keys from lokid: ", RouterID(seckey_topublic(identityKey)));
RouterID(seckey_topublic(identityKey)));
} }
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
curl_slist_free_all(list); curl_slist_free_all(list);

@ -74,7 +74,7 @@ namespace llarp
std::atomic_bool m_initialized; std::atomic_bool m_initialized;
std::atomic_bool m_needBackup; std::atomic_bool m_needBackup;
bool m_usingLokid = false; bool m_usingLokid = false;
std::string m_lokidRPCAddr = "127.0.0.1:22023"; std::string m_lokidRPCAddr = "127.0.0.1:22023";
std::string m_lokidRPCUser; std::string m_lokidRPCUser;
std::string m_lokidRPCPassword; std::string m_lokidRPCPassword;
@ -87,8 +87,10 @@ namespace llarp
/// ///
/// @param keygen is a function that will generate the key if needed /// @param keygen is a function that will generate the key if needed
static bool static bool
loadOrCreateKey(const std::string& filepath, llarp::SecretKey& key, loadOrCreateKey(
std::function< void(llarp::SecretKey& key) > keygen); const std::string& filepath,
llarp::SecretKey& key,
std::function<void(llarp::SecretKey& key)> keygen);
/// Requests the identity key from lokid via HTTP (curl) /// Requests the identity key from lokid via HTTP (curl)
bool bool

@ -9,7 +9,7 @@ namespace llarp
namespace consensus namespace consensus
{ {
/// consensus table /// consensus table
struct Table : public std::vector< RouterID > struct Table : public std::vector<RouterID>
{ {
ShortHash ShortHash
CalculateHash() const; CalculateHash() const;

@ -5,7 +5,7 @@
#include <cstdlib> #include <cstdlib>
constexpr size_t MAX_LINK_MSG_SIZE = 8192; constexpr size_t MAX_LINK_MSG_SIZE = 8192;
static constexpr auto DefaultLinkSessionLifetime = 1min; static constexpr auto DefaultLinkSessionLifetime = 1min;
constexpr size_t MaxSendQueueSize = 1024; constexpr size_t MaxSendQueueSize = 1024;
#endif #endif

@ -20,11 +20,9 @@ namespace llarp
/// default path lifetime in ms /// default path lifetime in ms
constexpr std::chrono::milliseconds default_lifetime = 20min; constexpr std::chrono::milliseconds default_lifetime = 20min;
/// minimum into lifetime we will advertise /// minimum into lifetime we will advertise
constexpr std::chrono::milliseconds min_intro_lifetime = constexpr std::chrono::milliseconds min_intro_lifetime = default_lifetime / 2;
default_lifetime / 2;
/// spacing frequency at which we try to build paths for introductions /// spacing frequency at which we try to build paths for introductions
constexpr std::chrono::milliseconds intro_path_spread = constexpr std::chrono::milliseconds intro_path_spread = default_lifetime / 5;
default_lifetime / 5;
/// Minimum paths to keep around for intros; mainly used at startup (the /// Minimum paths to keep around for intros; mainly used at startup (the
/// spread, above, should be able to maintain more than this number of paths /// spread, above, should be able to maintain more than this number of paths
/// normally once things are going). /// normally once things are going).

@ -13,8 +13,7 @@
#endif #endif
#if defined(_WIN32) && defined(RC_INVOKED) #if defined(_WIN32) && defined(RC_INVOKED)
#define LLARP_VERSION \ #define LLARP_VERSION LLARP_VERSION_MAJOR, LLARP_VERSION_MINOR, LLARP_VERSION_PATCH, 0
LLARP_VERSION_MAJOR, LLARP_VERSION_MINOR, LLARP_VERSION_PATCH, 0
#define MAKE_TRIPLET(X, Y, Z) TRIPLET_CAT(X, ., Y, ., Z) #define MAKE_TRIPLET(X, Y, Z) TRIPLET_CAT(X, ., Y, ., Z)
#define TRIPLET_CAT(X, D1, Y, D2, Z) X##D1##Y##D2##Z #define TRIPLET_CAT(X, D1, Y, D2, Z) X##D1##Y##D2##Z

@ -6,11 +6,11 @@
namespace llarp namespace llarp
{ {
// Given a full lokinet version of: lokinet-1.2.3-abc these are: // Given a full lokinet version of: lokinet-1.2.3-abc these are:
extern const std::array< uint16_t, 3 > VERSION; // [1, 2, 3] extern const std::array<uint16_t, 3> VERSION; // [1, 2, 3]
extern const std::array< uint64_t, 4 > ROUTER_VERSION; // [proto, 1, 2, 3] extern const std::array<uint64_t, 4> ROUTER_VERSION; // [proto, 1, 2, 3]
extern const char* const VERSION_STR; // "1.2.3" extern const char* const VERSION_STR; // "1.2.3"
extern const char* const VERSION_TAG; // "abc" extern const char* const VERSION_TAG; // "abc"
extern const char* const VERSION_FULL; // "lokinet-1.2.3-abc" extern const char* const VERSION_FULL; // "lokinet-1.2.3-abc"
extern const char* const RELEASE_MOTTO; extern const char* const RELEASE_MOTTO;
extern const char* const DEFAULT_NETID; extern const char* const DEFAULT_NETID;

@ -15,14 +15,14 @@
#include <cxxopts.hpp> #include <cxxopts.hpp>
#include <csignal> #include <csignal>
#if(__FreeBSD__) || (__OpenBSD__) || (__NetBSD__) #if (__FreeBSD__) || (__OpenBSD__) || (__NetBSD__)
#include <pthread_np.h> #include <pthread_np.h>
#endif #endif
namespace llarp namespace llarp
{ {
bool bool
Context::CallSafe(std::function< void(void) > f) Context::CallSafe(std::function<void(void)> f)
{ {
return logic && LogicCall(logic, f); return logic && LogicCall(logic, f);
} }
@ -31,9 +31,9 @@ namespace llarp
Context::Configure() Context::Configure()
{ {
// llarp::LogInfo("loading config at ", configfile); // llarp::LogInfo("loading config at ", configfile);
if(configfile.size()) if (configfile.size())
{ {
if(!config->Load(configfile.c_str())) if (!config->Load(configfile.c_str()))
{ {
config.release(); config.release();
llarp::LogError("failed to load config file ", configfile); llarp::LogError("failed to load config file ", configfile);
@ -42,19 +42,18 @@ namespace llarp
} }
// System config // System config
if(!config->system.pidfile.empty()) if (!config->system.pidfile.empty())
{ {
SetPIDFile(config->system.pidfile); SetPIDFile(config->system.pidfile);
} }
auto threads = config->router.workerThreads(); auto threads = config->router.workerThreads();
if(threads <= 0) if (threads <= 0)
threads = 1; threads = 1;
worker = std::make_shared< llarp::thread::ThreadPool >(threads, 1024, worker = std::make_shared<llarp::thread::ThreadPool>(threads, 1024, "llarp-worker");
"llarp-worker");
auto jobQueueSize = config->router.jobQueueSize(); auto jobQueueSize = config->router.jobQueueSize();
if(jobQueueSize < 1024) if (jobQueueSize < 1024)
jobQueueSize = 1024; jobQueueSize = 1024;
logic = std::make_shared< Logic >(jobQueueSize); logic = std::make_shared<Logic>(jobQueueSize);
nodedb_dir = config->netdb.nodedbDir(); nodedb_dir = config->netdb.nodedbDir();
@ -62,7 +61,7 @@ namespace llarp
} }
void void
Context::SetPIDFile(const std::string &fname) Context::SetPIDFile(const std::string& fname)
{ {
pidfile = fname; pidfile = fname;
} }
@ -82,7 +81,7 @@ namespace llarp
int int
Context::LoadDatabase() Context::LoadDatabase()
{ {
if(!llarp_nodedb::ensure_dir(nodedb_dir.c_str())) if (!llarp_nodedb::ensure_dir(nodedb_dir.c_str()))
{ {
llarp::LogError("nodedb_dir is incorrect"); llarp::LogError("nodedb_dir is incorrect");
return 0; return 0;
@ -95,20 +94,20 @@ namespace llarp
{ {
llarp::LogInfo(llarp::VERSION_FULL, " ", llarp::RELEASE_MOTTO); llarp::LogInfo(llarp::VERSION_FULL, " ", llarp::RELEASE_MOTTO);
llarp::LogInfo("starting up"); llarp::LogInfo("starting up");
if(mainloop == nullptr) if (mainloop == nullptr)
mainloop = llarp_make_ev_loop(); mainloop = llarp_make_ev_loop();
logic->set_event_loop(mainloop.get()); logic->set_event_loop(mainloop.get());
mainloop->set_logic(logic); mainloop->set_logic(logic);
crypto = std::make_unique< sodium::CryptoLibSodium >(); crypto = std::make_unique<sodium::CryptoLibSodium>();
cryptoManager = std::make_unique< CryptoManager >(crypto.get()); cryptoManager = std::make_unique<CryptoManager>(crypto.get());
router = std::make_unique< Router >(worker, mainloop, logic); router = std::make_unique<Router>(worker, mainloop, logic);
nodedb = std::make_unique< llarp_nodedb >(router->diskworker(), nodedb_dir); nodedb = std::make_unique<llarp_nodedb>(router->diskworker(), nodedb_dir);
if(!router->Configure(config.get(), nodedb.get())) if (!router->Configure(config.get(), nodedb.get()))
{ {
llarp::LogError("Failed to configure router"); llarp::LogError("Failed to configure router");
return 1; return 1;
@ -117,7 +116,7 @@ namespace llarp
// must be done after router is made so we can use its disk io worker // must be done after router is made so we can use its disk io worker
// must also be done after configure so that netid is properly set if it // must also be done after configure so that netid is properly set if it
// is provided by config // is provided by config
if(!this->LoadDatabase()) if (!this->LoadDatabase())
return 1; return 1;
return 0; return 0;
@ -126,21 +125,21 @@ namespace llarp
int int
Context::Run(llarp_main_runtime_opts opts) Context::Run(llarp_main_runtime_opts opts)
{ {
if(router == nullptr) if (router == nullptr)
{ {
// we are not set up so we should die // we are not set up so we should die
llarp::LogError("cannot run non configured context"); llarp::LogError("cannot run non configured context");
return 1; return 1;
} }
if(!WritePIDFile()) if (!WritePIDFile())
return 1; return 1;
// run // run
if(!router->StartJsonRpc()) if (!router->StartJsonRpc())
return 1; return 1;
if(!opts.background) if (!opts.background)
{ {
if(!router->Run()) if (!router->Run())
return 2; return 2;
} }
@ -148,7 +147,7 @@ namespace llarp
llarp::LogInfo("running mainloop"); llarp::LogInfo("running mainloop");
llarp_ev_loop_run_single_process(mainloop, logic); llarp_ev_loop_run_single_process(mainloop, logic);
if(closeWaiter) if (closeWaiter)
{ {
// inform promise if called by CloseAsync // inform promise if called by CloseAsync
closeWaiter->set_value(); closeWaiter->set_value();
@ -160,16 +159,16 @@ namespace llarp
Context::CloseAsync() Context::CloseAsync()
{ {
/// already closing /// already closing
if(closeWaiter) if (closeWaiter)
return; return;
if(CallSafe(std::bind(&Context::HandleSignal, this, SIGTERM))) if (CallSafe(std::bind(&Context::HandleSignal, this, SIGTERM)))
closeWaiter = std::make_unique< std::promise< void > >(); closeWaiter = std::make_unique<std::promise<void>>();
} }
void void
Context::Wait() Context::Wait()
{ {
if(closeWaiter) if (closeWaiter)
{ {
closeWaiter->get_future().wait(); closeWaiter->get_future().wait();
closeWaiter.reset(); closeWaiter.reset();
@ -179,7 +178,7 @@ namespace llarp
bool bool
Context::WritePIDFile() const Context::WritePIDFile() const
{ {
if(pidfile.size()) if (pidfile.size())
{ {
std::ofstream f(pidfile); std::ofstream f(pidfile);
f << std::to_string(getpid()); f << std::to_string(getpid());
@ -192,13 +191,13 @@ namespace llarp
void void
Context::RemovePIDFile() const Context::RemovePIDFile() const
{ {
if(pidfile.size()) if (pidfile.size())
{ {
fs::path f = pidfile; fs::path f = pidfile;
std::error_code ex; std::error_code ex;
if(fs::exists(f, ex)) if (fs::exists(f, ex))
{ {
if(!ex) if (!ex)
fs::remove(f); fs::remove(f);
} }
} }
@ -207,39 +206,38 @@ namespace llarp
void void
Context::HandleSignal(int sig) Context::HandleSignal(int sig)
{ {
if(sig == SIGINT || sig == SIGTERM) if (sig == SIGINT || sig == SIGTERM)
{ {
SigINT(); SigINT();
} }
// TODO(despair): implement hot-reloading config on NT // TODO(despair): implement hot-reloading config on NT
#ifndef _WIN32 #ifndef _WIN32
if(sig == SIGHUP) if (sig == SIGHUP)
{ {
llarp::LogInfo("SIGHUP"); llarp::LogInfo("SIGHUP");
if(router) if (router)
{ {
router->hiddenServiceContext().ForEachService( router->hiddenServiceContext().ForEachService(
[](const std::string &name, [](const std::string& name, const llarp::service::Endpoint_ptr& ep) -> bool {
const llarp::service::Endpoint_ptr &ep) -> bool {
ep->ResetInternalState(); ep->ResetInternalState();
llarp::LogInfo("Reset internal state for ", name); llarp::LogInfo("Reset internal state for ", name);
return true; return true;
}); });
router->PumpLL(); router->PumpLL();
Config newconfig; Config newconfig;
if(!newconfig.Load(configfile.c_str())) if (!newconfig.Load(configfile.c_str()))
{ {
llarp::LogError("failed to load config file ", configfile); llarp::LogError("failed to load config file ", configfile);
return; return;
} }
// validate config // validate config
if(!router->ValidateConfig(&newconfig)) if (!router->ValidateConfig(&newconfig))
{ {
llarp::LogWarn("new configuration is invalid"); llarp::LogWarn("new configuration is invalid");
return; return;
} }
// reconfigure // reconfigure
if(!router->Reconfigure(&newconfig)) if (!router->Reconfigure(&newconfig))
{ {
llarp::LogError("Failed to reconfigure so we will stop."); llarp::LogError("Failed to reconfigure so we will stop.");
router->Stop(); router->Stop();
@ -254,14 +252,14 @@ namespace llarp
void void
Context::SigINT() Context::SigINT()
{ {
if(router) if (router)
{ {
/// async stop router on sigint /// async stop router on sigint
router->Stop(); router->Stop();
} }
else else
{ {
if(logic) if (logic)
logic->stop(); logic->stop();
llarp_ev_loop_stop(mainloop); llarp_ev_loop_stop(mainloop);
Close(); Close();
@ -272,7 +270,7 @@ namespace llarp
Context::Close() Context::Close()
{ {
llarp::LogDebug("stop workers"); llarp::LogDebug("stop workers");
if(worker) if (worker)
worker->stop(); worker->stop();
llarp::LogDebug("free config"); llarp::LogDebug("free config");
@ -294,16 +292,16 @@ namespace llarp
} }
bool bool
Context::LoadConfig(const std::string &fname) Context::LoadConfig(const std::string& fname)
{ {
config = std::make_unique< Config >(); config = std::make_unique<Config>();
configfile = fname; configfile = fname;
return Configure(); return Configure();
} }
#ifdef LOKINET_HIVE #ifdef LOKINET_HIVE
void void
Context::InjectHive(tooling::RouterHive *hive) Context::InjectHive(tooling::RouterHive* hive)
{ {
router->hive = hive; router->hive = hive;
} }
@ -312,9 +310,9 @@ namespace llarp
struct llarp_main struct llarp_main
{ {
llarp_main(llarp_config *conf); llarp_main(llarp_config* conf);
~llarp_main() = default; ~llarp_main() = default;
std::shared_ptr< llarp::Context > ctx; std::shared_ptr<llarp::Context> ctx;
}; };
struct llarp_config struct llarp_config
@ -322,18 +320,18 @@ struct llarp_config
llarp::Config impl; llarp::Config impl;
llarp_config() = default; llarp_config() = default;
llarp_config(const llarp_config *other) : impl(other->impl) llarp_config(const llarp_config* other) : impl(other->impl)
{ {
} }
}; };
namespace llarp namespace llarp
{ {
llarp_config * llarp_config*
Config::Copy() const Config::Copy() const
{ {
llarp_config *ptr = new llarp_config(); llarp_config* ptr = new llarp_config();
ptr->impl = *this; ptr->impl = *this;
return ptr; return ptr;
} }
} // namespace llarp } // namespace llarp
@ -352,10 +350,10 @@ extern "C"
return sizeof(llarp_config); return sizeof(llarp_config);
} }
struct llarp_config * struct llarp_config*
llarp_default_config() llarp_default_config()
{ {
llarp_config *conf = new llarp_config(); llarp_config* conf = new llarp_config();
#ifdef ANDROID #ifdef ANDROID
// put andrid config overrides here // put andrid config overrides here
#endif #endif
@ -366,37 +364,37 @@ extern "C"
} }
void void
llarp_config_free(struct llarp_config *conf) llarp_config_free(struct llarp_config* conf)
{ {
if(conf) if (conf)
delete conf; delete conf;
} }
struct llarp_main * struct llarp_main*
llarp_main_init_from_config(struct llarp_config *conf) llarp_main_init_from_config(struct llarp_config* conf)
{ {
if(conf == nullptr) if (conf == nullptr)
return nullptr; return nullptr;
llarp_main *m = new llarp_main(conf); llarp_main* m = new llarp_main(conf);
if(m->ctx->Configure()) if (m->ctx->Configure())
return m; return m;
delete m; delete m;
return nullptr; return nullptr;
} }
bool bool
llarp_config_read_file(struct llarp_config *conf, const char *fname) llarp_config_read_file(struct llarp_config* conf, const char* fname)
{ {
if(conf == nullptr) if (conf == nullptr)
return false; return false;
return conf->impl.Load(fname); return conf->impl.Load(fname);
} }
bool bool
llarp_config_load_file(const char *fname, struct llarp_config **conf) llarp_config_load_file(const char* fname, struct llarp_config** conf)
{ {
llarp_config *c = new llarp_config(); llarp_config* c = new llarp_config();
if(c->impl.Load(fname)) if (c->impl.Load(fname))
{ {
*conf = c; *conf = c;
return true; return true;
@ -407,137 +405,135 @@ extern "C"
} }
void void
llarp_main_signal(struct llarp_main *ptr, int sig) llarp_main_signal(struct llarp_main* ptr, int sig)
{ {
LogicCall(ptr->ctx->logic, LogicCall(ptr->ctx->logic, std::bind(&llarp::Context::HandleSignal, ptr->ctx.get(), sig));
std::bind(&llarp::Context::HandleSignal, ptr->ctx.get(), sig));
} }
int int
llarp_main_setup(struct llarp_main *ptr) llarp_main_setup(struct llarp_main* ptr)
{ {
return ptr->ctx->Setup(); return ptr->ctx->Setup();
} }
int int
llarp_main_run(struct llarp_main *ptr, struct llarp_main_runtime_opts opts) llarp_main_run(struct llarp_main* ptr, struct llarp_main_runtime_opts opts)
{ {
return ptr->ctx->Run(opts); return ptr->ctx->Run(opts);
} }
const char * const char*
llarp_version() llarp_version()
{ {
return llarp::VERSION_FULL; return llarp::VERSION_FULL;
} }
ssize_t ssize_t
llarp_vpn_io_readpkt(struct llarp_vpn_pkt_reader *r, unsigned char *dst, llarp_vpn_io_readpkt(struct llarp_vpn_pkt_reader* r, unsigned char* dst, size_t dstlen)
size_t dstlen)
{ {
if(r == nullptr) if (r == nullptr)
return -1; return -1;
if(not r->queue.enabled()) if (not r->queue.enabled())
return -1; return -1;
auto pkt = r->queue.popFront(); auto pkt = r->queue.popFront();
ManagedBuffer mbuf = pkt.ConstBuffer(); ManagedBuffer mbuf = pkt.ConstBuffer();
const llarp_buffer_t &buf = mbuf; const llarp_buffer_t& buf = mbuf;
if(buf.sz > dstlen || buf.sz == 0) if (buf.sz > dstlen || buf.sz == 0)
return -1; return -1;
std::copy_n(buf.base, buf.sz, dst); std::copy_n(buf.base, buf.sz, dst);
return buf.sz; return buf.sz;
} }
bool bool
llarp_vpn_io_writepkt(struct llarp_vpn_pkt_writer *w, unsigned char *pktbuf, llarp_vpn_io_writepkt(struct llarp_vpn_pkt_writer* w, unsigned char* pktbuf, size_t pktlen)
size_t pktlen)
{ {
if(pktlen == 0 || pktbuf == nullptr) if (pktlen == 0 || pktbuf == nullptr)
return false; return false;
if(w == nullptr) if (w == nullptr)
return false; return false;
llarp_vpn_pkt_queue::Packet_t pkt; llarp_vpn_pkt_queue::Packet_t pkt;
llarp_buffer_t buf(pktbuf, pktlen); llarp_buffer_t buf(pktbuf, pktlen);
if(not pkt.Load(buf)) if (not pkt.Load(buf))
return false; return false;
return w->queue.pushBack(std::move(pkt)) return w->queue.pushBack(std::move(pkt)) == llarp::thread::QueueReturn::Success;
== llarp::thread::QueueReturn::Success;
} }
bool bool
llarp_main_inject_vpn_by_name(struct llarp_main *ptr, const char *name, llarp_main_inject_vpn_by_name(
struct llarp_vpn_io *io, struct llarp_main* ptr,
struct llarp_vpn_ifaddr_info info) const char* name,
struct llarp_vpn_io* io,
struct llarp_vpn_ifaddr_info info)
{ {
if(name == nullptr || io == nullptr) if (name == nullptr || io == nullptr)
return false; return false;
if(ptr == nullptr || ptr->ctx == nullptr || ptr->ctx->router == nullptr) if (ptr == nullptr || ptr->ctx == nullptr || ptr->ctx->router == nullptr)
return false; return false;
auto ep = ptr->ctx->router->hiddenServiceContext().GetEndpointByName(name); auto ep = ptr->ctx->router->hiddenServiceContext().GetEndpointByName(name);
return ep && ep->InjectVPN(io, info); return ep && ep->InjectVPN(io, info);
} }
void void
llarp_vpn_io_close_async(struct llarp_vpn_io *io) llarp_vpn_io_close_async(struct llarp_vpn_io* io)
{ {
if(io == nullptr || io->impl == nullptr) if (io == nullptr || io->impl == nullptr)
return; return;
static_cast< llarp_vpn_io_impl * >(io->impl)->AsyncClose(); static_cast<llarp_vpn_io_impl*>(io->impl)->AsyncClose();
} }
bool bool
llarp_vpn_io_init(struct llarp_main *ptr, struct llarp_vpn_io *io) llarp_vpn_io_init(struct llarp_main* ptr, struct llarp_vpn_io* io)
{ {
if(io == nullptr || ptr == nullptr) if (io == nullptr || ptr == nullptr)
return false; return false;
llarp_vpn_io_impl *impl = new llarp_vpn_io_impl(ptr, io); llarp_vpn_io_impl* impl = new llarp_vpn_io_impl(ptr, io);
io->impl = impl; io->impl = impl;
return true; return true;
} }
struct llarp_vpn_pkt_writer * struct llarp_vpn_pkt_writer*
llarp_vpn_io_packet_writer(struct llarp_vpn_io *io) llarp_vpn_io_packet_writer(struct llarp_vpn_io* io)
{ {
if(io == nullptr || io->impl == nullptr) if (io == nullptr || io->impl == nullptr)
return nullptr; return nullptr;
llarp_vpn_io_impl *vpn = static_cast< llarp_vpn_io_impl * >(io->impl); llarp_vpn_io_impl* vpn = static_cast<llarp_vpn_io_impl*>(io->impl);
return &vpn->writer; return &vpn->writer;
} }
struct llarp_vpn_pkt_reader * struct llarp_vpn_pkt_reader*
llarp_vpn_io_packet_reader(struct llarp_vpn_io *io) llarp_vpn_io_packet_reader(struct llarp_vpn_io* io)
{ {
if(io == nullptr || io->impl == nullptr) if (io == nullptr || io->impl == nullptr)
return nullptr; return nullptr;
llarp_vpn_io_impl *vpn = static_cast< llarp_vpn_io_impl * >(io->impl); llarp_vpn_io_impl* vpn = static_cast<llarp_vpn_io_impl*>(io->impl);
return &vpn->reader; return &vpn->reader;
} }
void void
llarp_main_free(struct llarp_main *ptr) llarp_main_free(struct llarp_main* ptr)
{ {
delete ptr; delete ptr;
} }
const char * const char*
llarp_main_get_default_endpoint_name(struct llarp_main *) llarp_main_get_default_endpoint_name(struct llarp_main*)
{ {
return "default"; return "default";
} }
void void
llarp_main_stop(struct llarp_main *ptr) llarp_main_stop(struct llarp_main* ptr)
{ {
if(ptr == nullptr) if (ptr == nullptr)
return; return;
ptr->ctx->CloseAsync(); ptr->ctx->CloseAsync();
ptr->ctx->Wait(); ptr->ctx->Wait();
} }
bool bool
llarp_main_configure(struct llarp_main *ptr, struct llarp_config *conf) llarp_main_configure(struct llarp_main* ptr, struct llarp_config* conf)
{ {
if(ptr == nullptr || conf == nullptr) if (ptr == nullptr || conf == nullptr)
return false; return false;
// give new config // give new config
ptr->ctx->config.reset(new llarp::Config(conf->impl)); ptr->ctx->config.reset(new llarp::Config(conf->impl));
@ -545,13 +541,13 @@ extern "C"
} }
bool bool
llarp_main_is_running(struct llarp_main *ptr) llarp_main_is_running(struct llarp_main* ptr)
{ {
return ptr && ptr->ctx->router && ptr->ctx->router->IsRunning(); return ptr && ptr->ctx->router && ptr->ctx->router->IsRunning();
} }
} }
llarp_main::llarp_main(llarp_config *conf) llarp_main::llarp_main(llarp_config* conf)
: ctx(new llarp::Context()) : ctx(new llarp::Context())
{ {
@ -560,10 +556,10 @@ llarp_main::llarp_main(llarp_config *conf)
namespace llarp namespace llarp
{ {
std::shared_ptr< Context > std::shared_ptr<Context>
Context::Get(llarp_main *m) Context::Get(llarp_main* m)
{ {
if(m == nullptr || m->ctx == nullptr) if (m == nullptr || m->ctx == nullptr)
return nullptr; return nullptr;
return m->ctx; return m->ctx;
} }

@ -5,21 +5,21 @@
#include <libntrup/ntru.h> #include <libntrup/ntru.h>
static constexpr uint32_t PUBKEYSIZE = 32; static constexpr uint32_t PUBKEYSIZE = 32;
static constexpr uint32_t SECKEYSIZE = 64; static constexpr uint32_t SECKEYSIZE = 64;
static constexpr uint32_t NONCESIZE = 24; static constexpr uint32_t NONCESIZE = 24;
static constexpr uint32_t SHAREDKEYSIZE = 32; static constexpr uint32_t SHAREDKEYSIZE = 32;
static constexpr uint32_t HASHSIZE = 64; static constexpr uint32_t HASHSIZE = 64;
static constexpr uint32_t SHORTHASHSIZE = 32; static constexpr uint32_t SHORTHASHSIZE = 32;
static constexpr uint32_t HMACSECSIZE = 32; static constexpr uint32_t HMACSECSIZE = 32;
static constexpr uint32_t SIGSIZE = 64; static constexpr uint32_t SIGSIZE = 64;
static constexpr uint32_t TUNNONCESIZE = 32; static constexpr uint32_t TUNNONCESIZE = 32;
static constexpr uint32_t HMACSIZE = 32; static constexpr uint32_t HMACSIZE = 32;
static constexpr uint32_t PATHIDSIZE = 16; static constexpr uint32_t PATHIDSIZE = 16;
static constexpr uint32_t PQ_CIPHERTEXTSIZE = crypto_kem_CIPHERTEXTBYTES; static constexpr uint32_t PQ_CIPHERTEXTSIZE = crypto_kem_CIPHERTEXTBYTES;
static constexpr uint32_t PQ_PUBKEYSIZE = crypto_kem_PUBLICKEYBYTES; static constexpr uint32_t PQ_PUBKEYSIZE = crypto_kem_PUBLICKEYBYTES;
static constexpr uint32_t PQ_SECRETKEYSIZE = crypto_kem_SECRETKEYBYTES; static constexpr uint32_t PQ_SECRETKEYSIZE = crypto_kem_SECRETKEYBYTES;
static constexpr uint32_t PQ_KEYPAIRSIZE = (PQ_SECRETKEYSIZE + PQ_PUBKEYSIZE); static constexpr uint32_t PQ_KEYPAIRSIZE = (PQ_SECRETKEYSIZE + PQ_PUBKEYSIZE);
#endif #endif

@ -26,83 +26,77 @@ namespace llarp
/// xchacha symmetric cipher /// xchacha symmetric cipher
virtual bool virtual bool
xchacha20(const llarp_buffer_t &, const SharedSecret &, xchacha20(const llarp_buffer_t&, const SharedSecret&, const TunnelNonce&) = 0;
const TunnelNonce &) = 0;
/// xchacha symmetric cipher (multibuffer) /// xchacha symmetric cipher (multibuffer)
virtual bool virtual bool
xchacha20_alt(const llarp_buffer_t &, const llarp_buffer_t &, xchacha20_alt(
const SharedSecret &, const byte_t *) = 0; const llarp_buffer_t&, const llarp_buffer_t&, const SharedSecret&, const byte_t*) = 0;
/// path dh creator's side /// path dh creator's side
virtual bool virtual bool
dh_client(SharedSecret &, const PubKey &, const SecretKey &, dh_client(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&) = 0;
const TunnelNonce &) = 0;
/// path dh relay side /// path dh relay side
virtual bool virtual bool
dh_server(SharedSecret &, const PubKey &, const SecretKey &, dh_server(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&) = 0;
const TunnelNonce &) = 0;
/// transport dh client side /// transport dh client side
virtual bool virtual bool
transport_dh_client(SharedSecret &, const PubKey &, const SecretKey &, transport_dh_client(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&) = 0;
const TunnelNonce &) = 0;
/// transport dh server side /// transport dh server side
virtual bool virtual bool
transport_dh_server(SharedSecret &, const PubKey &, const SecretKey &, transport_dh_server(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&) = 0;
const TunnelNonce &) = 0;
/// blake2b 256 bit /// blake2b 256 bit
virtual bool virtual bool
shorthash(ShortHash &, const llarp_buffer_t &) = 0; shorthash(ShortHash&, const llarp_buffer_t&) = 0;
/// blake2s 256 bit "hmac" (keyed hash) /// blake2s 256 bit "hmac" (keyed hash)
virtual bool virtual bool
hmac(byte_t *, const llarp_buffer_t &, const SharedSecret &) = 0; hmac(byte_t*, const llarp_buffer_t&, const SharedSecret&) = 0;
/// ed25519 sign /// ed25519 sign
virtual bool virtual bool
sign(Signature &, const SecretKey &, const llarp_buffer_t &) = 0; sign(Signature&, const SecretKey&, const llarp_buffer_t&) = 0;
/// ed25519 sign (custom with derived keys) /// ed25519 sign (custom with derived keys)
virtual bool virtual bool
sign(Signature &, const PrivateKey &, const llarp_buffer_t &) = 0; sign(Signature&, const PrivateKey&, const llarp_buffer_t&) = 0;
/// ed25519 verify /// ed25519 verify
virtual bool virtual bool
verify(const PubKey &, const llarp_buffer_t &, const Signature &) = 0; verify(const PubKey&, const llarp_buffer_t&, const Signature&) = 0;
/// derive sub keys for public keys /// derive sub keys for public keys
virtual bool virtual bool
derive_subkey(PubKey &, const PubKey &, uint64_t, derive_subkey(PubKey&, const PubKey&, uint64_t, const AlignedBuffer<32>* = nullptr) = 0;
const AlignedBuffer< 32 > * = nullptr) = 0;
/// derive sub keys for private keys /// derive sub keys for private keys
virtual bool virtual bool
derive_subkey_private(PrivateKey &, const SecretKey &, uint64_t, derive_subkey_private(
const AlignedBuffer< 32 > * = nullptr) = 0; PrivateKey&, const SecretKey&, uint64_t, const AlignedBuffer<32>* = nullptr) = 0;
/// seed to secretkey /// seed to secretkey
virtual bool virtual bool
seed_to_secretkey(llarp::SecretKey &, const llarp::IdentitySecret &) = 0; seed_to_secretkey(llarp::SecretKey&, const llarp::IdentitySecret&) = 0;
/// randomize buffer /// randomize buffer
virtual void virtual void
randomize(const llarp_buffer_t &) = 0; randomize(const llarp_buffer_t&) = 0;
/// randomizer memory /// randomizer memory
virtual void virtual void
randbytes(byte_t *, size_t) = 0; randbytes(byte_t*, size_t) = 0;
/// generate signing keypair /// generate signing keypair
virtual void virtual void
identity_keygen(SecretKey &) = 0; identity_keygen(SecretKey&) = 0;
/// generate encryption keypair /// generate encryption keypair
virtual void virtual void
encryption_keygen(SecretKey &) = 0; encryption_keygen(SecretKey&) = 0;
/// generate post quantum encrytion key /// generate post quantum encrytion key
virtual void virtual void
pqe_keygen(PQKeyPair &) = 0; pqe_keygen(PQKeyPair&) = 0;
/// post quantum decrypt (buffer, sharedkey_dst, sec) /// post quantum decrypt (buffer, sharedkey_dst, sec)
virtual bool virtual bool
pqe_decrypt(const PQCipherBlock &, SharedSecret &, const byte_t *) = 0; pqe_decrypt(const PQCipherBlock&, SharedSecret&, const byte_t*) = 0;
/// post quantum encrypt (buffer, sharedkey_dst, pub) /// post quantum encrypt (buffer, sharedkey_dst, pub)
virtual bool virtual bool
pqe_encrypt(PQCipherBlock &, SharedSecret &, const PQPubKey &) = 0; pqe_encrypt(PQCipherBlock&, SharedSecret&, const PQPubKey&) = 0;
virtual bool virtual bool
check_identity_privkey(const SecretKey &) = 0; check_identity_privkey(const SecretKey&) = 0;
}; };
inline Crypto::~Crypto() = default; inline Crypto::~Crypto() = default;
@ -111,24 +105,24 @@ namespace llarp
uint64_t uint64_t
randint(); randint();
const byte_t * const byte_t*
seckey_topublic(const SecretKey &secret); seckey_topublic(const SecretKey& secret);
const byte_t * const byte_t*
pq_keypair_to_public(const PQKeyPair &keypair); pq_keypair_to_public(const PQKeyPair& keypair);
const byte_t * const byte_t*
pq_keypair_to_secret(const PQKeyPair &keypair); pq_keypair_to_secret(const PQKeyPair& keypair);
struct CryptoManager struct CryptoManager
{ {
private: private:
static Crypto *m_crypto; static Crypto* m_crypto;
Crypto *m_prevCrypto; Crypto* m_prevCrypto;
public: public:
CryptoManager(Crypto *crypto) : m_prevCrypto(m_crypto) CryptoManager(Crypto* crypto) : m_prevCrypto(m_crypto)
{ {
m_crypto = crypto; m_crypto = crypto;
} }
@ -138,13 +132,13 @@ namespace llarp
m_crypto = m_prevCrypto; m_crypto = m_prevCrypto;
} }
static Crypto * static Crypto*
instance() instance()
{ {
#ifdef NDEBUG #ifdef NDEBUG
return m_crypto; return m_crypto;
#else #else
if(m_crypto) if (m_crypto)
return m_crypto; return m_crypto;
assert(false && "Cryptomanager::instance() was undefined"); assert(false && "Cryptomanager::instance() was undefined");

@ -23,13 +23,16 @@ namespace llarp
namespace sodium namespace sodium
{ {
static bool static bool
dh(llarp::SharedSecret &out, const PubKey &client_pk, dh(llarp::SharedSecret& out,
const PubKey &server_pk, const uint8_t *themPub, const SecretKey &usSec) const PubKey& client_pk,
const PubKey& server_pk,
const uint8_t* themPub,
const SecretKey& usSec)
{ {
llarp::SharedSecret shared; llarp::SharedSecret shared;
crypto_generichash_state h; crypto_generichash_state h;
if(crypto_scalarmult_curve25519(shared.data(), usSec.data(), themPub)) if (crypto_scalarmult_curve25519(shared.data(), usSec.data(), themPub))
{ {
return false; return false;
} }
@ -42,15 +45,14 @@ namespace llarp
} }
static bool static bool
dh_client_priv(llarp::SharedSecret &shared, const PubKey &pk, dh_client_priv(
const SecretKey &sk, const TunnelNonce &n) llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n)
{ {
llarp::SharedSecret dh_result; llarp::SharedSecret dh_result;
if(dh(dh_result, sk.toPublic(), pk, pk.data(), sk)) if (dh(dh_result, sk.toPublic(), pk, pk.data(), sk))
{ {
return crypto_generichash_blake2b(shared.data(), 32, n.data(), 32, return crypto_generichash_blake2b(shared.data(), 32, n.data(), 32, dh_result.data(), 32)
dh_result.data(), 32)
!= -1; != -1;
} }
llarp::LogWarn("crypto::dh_client - dh failed"); llarp::LogWarn("crypto::dh_client - dh failed");
@ -58,14 +60,13 @@ namespace llarp
} }
static bool static bool
dh_server_priv(llarp::SharedSecret &shared, const PubKey &pk, dh_server_priv(
const SecretKey &sk, const TunnelNonce &n) llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n)
{ {
llarp::SharedSecret dh_result; llarp::SharedSecret dh_result;
if(dh(dh_result, pk, sk.toPublic(), pk.data(), sk)) if (dh(dh_result, pk, sk.toPublic(), pk.data(), sk))
{ {
return crypto_generichash_blake2b(shared.data(), 32, n.data(), 32, return crypto_generichash_blake2b(shared.data(), 32, n.data(), 32, dh_result.data(), 32)
dh_result.data(), 32)
!= -1; != -1;
} }
llarp::LogWarn("crypto::dh_server - dh failed"); llarp::LogWarn("crypto::dh_server - dh failed");
@ -74,12 +75,12 @@ namespace llarp
CryptoLibSodium::CryptoLibSodium() CryptoLibSodium::CryptoLibSodium()
{ {
if(sodium_init() == -1) if (sodium_init() == -1)
{ {
throw std::runtime_error("sodium_init() returned -1"); throw std::runtime_error("sodium_init() returned -1");
} }
char *avx2 = std::getenv("AVX2_FORCE_DISABLE"); char* avx2 = std::getenv("AVX2_FORCE_DISABLE");
if(avx2 && std::string(avx2) == "1") if (avx2 && std::string(avx2) == "1")
{ {
ntru_init(1); ntru_init(1);
} }
@ -88,97 +89,84 @@ namespace llarp
ntru_init(0); ntru_init(0);
} }
int seed = 0; int seed = 0;
randombytes(reinterpret_cast< unsigned char * >(&seed), sizeof(seed)); randombytes(reinterpret_cast<unsigned char*>(&seed), sizeof(seed));
srand(seed); srand(seed);
} }
bool bool
CryptoLibSodium::xchacha20(const llarp_buffer_t &buff, CryptoLibSodium::xchacha20(
const SharedSecret &k, const TunnelNonce &n) const llarp_buffer_t& buff, const SharedSecret& k, const TunnelNonce& n)
{ {
return crypto_stream_xchacha20_xor(buff.base, buff.base, buff.sz, return crypto_stream_xchacha20_xor(buff.base, buff.base, buff.sz, n.data(), k.data()) == 0;
n.data(), k.data())
== 0;
} }
bool bool
CryptoLibSodium::xchacha20_alt(const llarp_buffer_t &out, CryptoLibSodium::xchacha20_alt(
const llarp_buffer_t &in, const llarp_buffer_t& out, const llarp_buffer_t& in, const SharedSecret& k, const byte_t* n)
const SharedSecret &k, const byte_t *n)
{ {
if(in.sz > out.sz) if (in.sz > out.sz)
return false; return false;
return crypto_stream_xchacha20_xor(out.base, in.base, in.sz, n, k.data()) return crypto_stream_xchacha20_xor(out.base, in.base, in.sz, n, k.data()) == 0;
== 0;
} }
bool bool
CryptoLibSodium::dh_client(llarp::SharedSecret &shared, const PubKey &pk, CryptoLibSodium::dh_client(
const SecretKey &sk, const TunnelNonce &n) llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n)
{ {
return dh_client_priv(shared, pk, sk, n); return dh_client_priv(shared, pk, sk, n);
} }
/// path dh relay side /// path dh relay side
bool bool
CryptoLibSodium::dh_server(llarp::SharedSecret &shared, const PubKey &pk, CryptoLibSodium::dh_server(
const SecretKey &sk, const TunnelNonce &n) llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n)
{ {
return dh_server_priv(shared, pk, sk, n); return dh_server_priv(shared, pk, sk, n);
} }
/// transport dh client side /// transport dh client side
bool bool
CryptoLibSodium::transport_dh_client(llarp::SharedSecret &shared, CryptoLibSodium::transport_dh_client(
const PubKey &pk, const SecretKey &sk, llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n)
const TunnelNonce &n)
{ {
return dh_client_priv(shared, pk, sk, n); return dh_client_priv(shared, pk, sk, n);
} }
/// transport dh server side /// transport dh server side
bool bool
CryptoLibSodium::transport_dh_server(llarp::SharedSecret &shared, CryptoLibSodium::transport_dh_server(
const PubKey &pk, const SecretKey &sk, llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n)
const TunnelNonce &n)
{ {
return dh_server_priv(shared, pk, sk, n); return dh_server_priv(shared, pk, sk, n);
} }
bool bool
CryptoLibSodium::shorthash(ShortHash &result, const llarp_buffer_t &buff) CryptoLibSodium::shorthash(ShortHash& result, const llarp_buffer_t& buff)
{ {
return crypto_generichash_blake2b(result.data(), ShortHash::SIZE, return crypto_generichash_blake2b(
buff.base, buff.sz, nullptr, 0) result.data(), ShortHash::SIZE, buff.base, buff.sz, nullptr, 0)
!= -1; != -1;
} }
bool bool
CryptoLibSodium::hmac(byte_t *result, const llarp_buffer_t &buff, CryptoLibSodium::hmac(byte_t* result, const llarp_buffer_t& buff, const SharedSecret& secret)
const SharedSecret &secret)
{ {
return crypto_generichash_blake2b(result, HMACSIZE, buff.base, buff.sz, return crypto_generichash_blake2b(
secret.data(), HMACSECSIZE) result, HMACSIZE, buff.base, buff.sz, secret.data(), HMACSECSIZE)
!= -1; != -1;
} }
static bool static bool
hash(uint8_t *result, const llarp_buffer_t &buff) hash(uint8_t* result, const llarp_buffer_t& buff)
{ {
return crypto_generichash_blake2b(result, HASHSIZE, buff.base, buff.sz, return crypto_generichash_blake2b(result, HASHSIZE, buff.base, buff.sz, nullptr, 0) != -1;
nullptr, 0)
!= -1;
} }
bool bool
CryptoLibSodium::sign(Signature &sig, const SecretKey &secret, CryptoLibSodium::sign(Signature& sig, const SecretKey& secret, const llarp_buffer_t& buf)
const llarp_buffer_t &buf)
{ {
return crypto_sign_detached(sig.data(), nullptr, buf.base, buf.sz, return crypto_sign_detached(sig.data(), nullptr, buf.base, buf.sz, secret.data()) != -1;
secret.data())
!= -1;
} }
bool bool
CryptoLibSodium::sign(Signature &sig, const PrivateKey &privkey, CryptoLibSodium::sign(Signature& sig, const PrivateKey& privkey, const llarp_buffer_t& buf)
const llarp_buffer_t &buf)
{ {
PubKey pubkey; PubKey pubkey;
@ -222,35 +210,32 @@ namespace llarp
} }
bool bool
CryptoLibSodium::verify(const PubKey &pub, const llarp_buffer_t &buf, CryptoLibSodium::verify(const PubKey& pub, const llarp_buffer_t& buf, const Signature& sig)
const Signature &sig)
{ {
return crypto_sign_verify_detached(sig.data(), buf.base, buf.sz, return crypto_sign_verify_detached(sig.data(), buf.base, buf.sz, pub.data()) != -1;
pub.data())
!= -1;
} }
/// clamp a 32 byte ec point /// clamp a 32 byte ec point
static void static void
clamp_ed25519(byte_t *out) clamp_ed25519(byte_t* out)
{ {
out[0] &= 248; out[0] &= 248;
out[31] &= 127; out[31] &= 127;
out[31] |= 64; out[31] |= 64;
} }
template < typename K > template <typename K>
static K static K
clamp(const K &p) clamp(const K& p)
{ {
K out = p; K out = p;
clamp_ed25519(out); clamp_ed25519(out);
return out; return out;
} }
template < typename K > template <typename K>
static bool static bool
is_clamped(const K &key) is_clamped(const K& key)
{ {
K other(key); K other(key);
clamp_ed25519(other.data()); clamp_ed25519(other.data());
@ -262,11 +247,12 @@ namespace llarp
"can't in the and by be or then before so just face it this text hurts " "can't in the and by be or then before so just face it this text hurts "
"to read? lokinet yolo!"; "to read? lokinet yolo!";
template < typename K > template <typename K>
static bool make_scalar(AlignedBuffer< 32 > &out, const K &k, uint64_t i) static bool
make_scalar(AlignedBuffer<32>& out, const K& k, uint64_t i)
{ {
// b = BLIND-STRING || k || i // b = BLIND-STRING || k || i
std::array< byte_t, 160 + K::SIZE + sizeof(uint64_t) > buf; std::array<byte_t, 160 + K::SIZE + sizeof(uint64_t)> buf;
std::copy(derived_key_hash_str, derived_key_hash_str + 160, buf.begin()); std::copy(derived_key_hash_str, derived_key_hash_str + 160, buf.begin());
std::copy(k.begin(), k.end(), buf.begin() + 160); std::copy(k.begin(), k.end(), buf.begin() + 160);
htole64buf(buf.data() + 160 + K::SIZE, i); htole64buf(buf.data() + 160 + K::SIZE, i);
@ -274,38 +260,39 @@ namespace llarp
// h = make_point(n) // h = make_point(n)
ShortHash n; ShortHash n;
return -1 return -1
!= crypto_generichash_blake2b(n.data(), ShortHash::SIZE, buf.data(), != crypto_generichash_blake2b(
buf.size(), nullptr, 0) n.data(), ShortHash::SIZE, buf.data(), buf.size(), nullptr, 0)
&& -1 != crypto_core_ed25519_from_uniform(out.data(), n.data()); && -1 != crypto_core_ed25519_from_uniform(out.data(), n.data());
} }
static AlignedBuffer< 32 > zero; static AlignedBuffer<32> zero;
bool bool
CryptoLibSodium::derive_subkey(PubKey &out_pubkey, CryptoLibSodium::derive_subkey(
const PubKey &root_pubkey, uint64_t key_n, PubKey& out_pubkey,
const AlignedBuffer< 32 > *hash) const PubKey& root_pubkey,
uint64_t key_n,
const AlignedBuffer<32>* hash)
{ {
// scalar h = H( BLIND-STRING || root_pubkey || key_n ) // scalar h = H( BLIND-STRING || root_pubkey || key_n )
AlignedBuffer< 32 > h; AlignedBuffer<32> h;
if(hash) if (hash)
h = *hash; h = *hash;
else if(not make_scalar(h, root_pubkey, key_n)) else if (not make_scalar(h, root_pubkey, key_n))
{ {
LogError("cannot make scalar"); LogError("cannot make scalar");
return false; return false;
} }
return 0 return 0 == crypto_scalarmult_ed25519(out_pubkey.data(), h.data(), root_pubkey.data());
== crypto_scalarmult_ed25519(out_pubkey.data(), h.data(),
root_pubkey.data());
} }
bool bool
CryptoLibSodium::derive_subkey_private(PrivateKey &out_key, CryptoLibSodium::derive_subkey_private(
const SecretKey &root_key, PrivateKey& out_key,
uint64_t key_n, const SecretKey& root_key,
const AlignedBuffer< 32 > *hash) uint64_t key_n,
const AlignedBuffer<32>* hash)
{ {
// Derives a private subkey from a root key. // Derives a private subkey from a root key.
// //
@ -339,10 +326,10 @@ namespace llarp
// //
const auto root_pubkey = root_key.toPublic(); const auto root_pubkey = root_key.toPublic();
AlignedBuffer< 32 > h; AlignedBuffer<32> h;
if(hash) if (hash)
h = *hash; h = *hash;
else if(not make_scalar(h, root_pubkey, key_n)) else if (not make_scalar(h, root_pubkey, key_n))
{ {
LogError("cannot make scalar"); LogError("cannot make scalar");
return false; return false;
@ -353,45 +340,42 @@ namespace llarp
h[31] |= 64; h[31] |= 64;
PrivateKey a; PrivateKey a;
if(!root_key.toPrivate(a)) if (!root_key.toPrivate(a))
return false; return false;
// a' = ha // a' = ha
crypto_core_ed25519_scalar_mul(out_key.data(), h.data(), a.data()); crypto_core_ed25519_scalar_mul(out_key.data(), h.data(), a.data());
// s' = H(h || s) // s' = H(h || s)
std::array< byte_t, 64 > buf; std::array<byte_t, 64> buf;
std::copy(h.begin(), h.end(), buf.begin()); std::copy(h.begin(), h.end(), buf.begin());
std::copy(a.signingHash(), a.signingHash() + 32, buf.begin() + 32); std::copy(a.signingHash(), a.signingHash() + 32, buf.begin() + 32);
return -1 return -1
!= crypto_generichash_blake2b(out_key.signingHash(), 32, buf.data(), != crypto_generichash_blake2b(
buf.size(), nullptr, 0); out_key.signingHash(), 32, buf.data(), buf.size(), nullptr, 0);
return true; return true;
} }
bool bool
CryptoLibSodium::seed_to_secretkey(llarp::SecretKey &secret, CryptoLibSodium::seed_to_secretkey(llarp::SecretKey& secret, const llarp::IdentitySecret& seed)
const llarp::IdentitySecret &seed)
{ {
return crypto_sign_ed25519_seed_keypair(secret.data() + 32, secret.data(), return crypto_sign_ed25519_seed_keypair(secret.data() + 32, secret.data(), seed.data()) != -1;
seed.data())
!= -1;
} }
void void
CryptoLibSodium::randomize(const llarp_buffer_t &buff) CryptoLibSodium::randomize(const llarp_buffer_t& buff)
{ {
randombytes((unsigned char *)buff.base, buff.sz); randombytes((unsigned char*)buff.base, buff.sz);
} }
void void
CryptoLibSodium::randbytes(byte_t *ptr, size_t sz) CryptoLibSodium::randbytes(byte_t* ptr, size_t sz)
{ {
randombytes((unsigned char *)ptr, sz); randombytes((unsigned char*)ptr, sz);
} }
void void
CryptoLibSodium::identity_keygen(llarp::SecretKey &keys) CryptoLibSodium::identity_keygen(llarp::SecretKey& keys)
{ {
PubKey pk; PubKey pk;
int result = crypto_sign_keypair(pk.data(), keys.data()); int result = crypto_sign_keypair(pk.data(), keys.data());
@ -405,20 +389,20 @@ namespace llarp
} }
bool bool
CryptoLibSodium::check_identity_privkey(const llarp::SecretKey &keys) CryptoLibSodium::check_identity_privkey(const llarp::SecretKey& keys)
{ {
AlignedBuffer< crypto_sign_SEEDBYTES > seed; AlignedBuffer<crypto_sign_SEEDBYTES> seed;
llarp::PubKey pk; llarp::PubKey pk;
llarp::SecretKey sk; llarp::SecretKey sk;
if(crypto_sign_ed25519_sk_to_seed(seed.data(), keys.data()) == -1) if (crypto_sign_ed25519_sk_to_seed(seed.data(), keys.data()) == -1)
return false; return false;
if(crypto_sign_seed_keypair(pk.data(), sk.data(), seed.data()) == -1) if (crypto_sign_seed_keypair(pk.data(), sk.data(), seed.data()) == -1)
return false; return false;
return keys.toPublic() == pk && sk == keys; return keys.toPublic() == pk && sk == keys;
} }
void void
CryptoLibSodium::encryption_keygen(llarp::SecretKey &keys) CryptoLibSodium::encryption_keygen(llarp::SecretKey& keys)
{ {
auto d = keys.data(); auto d = keys.data();
randbytes(d, 32); randbytes(d, 32);
@ -426,44 +410,40 @@ namespace llarp
} }
bool bool
CryptoLibSodium::pqe_encrypt(PQCipherBlock &ciphertext, CryptoLibSodium::pqe_encrypt(
SharedSecret &sharedkey, PQCipherBlock& ciphertext, SharedSecret& sharedkey, const PQPubKey& pubkey)
const PQPubKey &pubkey)
{ {
return crypto_kem_enc(ciphertext.data(), sharedkey.data(), pubkey.data()) return crypto_kem_enc(ciphertext.data(), sharedkey.data(), pubkey.data()) != -1;
!= -1;
} }
bool bool
CryptoLibSodium::pqe_decrypt(const PQCipherBlock &ciphertext, CryptoLibSodium::pqe_decrypt(
SharedSecret &sharedkey, const PQCipherBlock& ciphertext, SharedSecret& sharedkey, const byte_t* secretkey)
const byte_t *secretkey)
{ {
return crypto_kem_dec(sharedkey.data(), ciphertext.data(), secretkey) return crypto_kem_dec(sharedkey.data(), ciphertext.data(), secretkey) != -1;
!= -1;
} }
void void
CryptoLibSodium::pqe_keygen(PQKeyPair &keypair) CryptoLibSodium::pqe_keygen(PQKeyPair& keypair)
{ {
auto d = keypair.data(); auto d = keypair.data();
crypto_kem_keypair(d + PQ_SECRETKEYSIZE, d); crypto_kem_keypair(d + PQ_SECRETKEYSIZE, d);
} }
} // namespace sodium } // namespace sodium
const byte_t * const byte_t*
seckey_topublic(const SecretKey &sec) seckey_topublic(const SecretKey& sec)
{ {
return sec.data() + 32; return sec.data() + 32;
} }
const byte_t * const byte_t*
pq_keypair_to_public(const PQKeyPair &k) pq_keypair_to_public(const PQKeyPair& k)
{ {
return k.data() + PQ_SECRETKEYSIZE; return k.data() + PQ_SECRETKEYSIZE;
} }
const byte_t * const byte_t*
pq_keypair_to_secret(const PQKeyPair &k) pq_keypair_to_secret(const PQKeyPair& k)
{ {
return k.data(); return k.data();
} }
@ -472,7 +452,7 @@ namespace llarp
randint() randint()
{ {
uint64_t i; uint64_t i;
randombytes((byte_t *)&i, sizeof(i)); randombytes((byte_t*)&i, sizeof(i));
return i; return i;
} }

@ -15,89 +15,91 @@ namespace llarp
/// xchacha symmetric cipher /// xchacha symmetric cipher
bool bool
xchacha20(const llarp_buffer_t &, const SharedSecret &, xchacha20(const llarp_buffer_t&, const SharedSecret&, const TunnelNonce&) override;
const TunnelNonce &) override;
/// xchacha symmetric cipher (multibuffer) /// xchacha symmetric cipher (multibuffer)
bool bool
xchacha20_alt(const llarp_buffer_t &, const llarp_buffer_t &, xchacha20_alt(
const SharedSecret &, const byte_t *) override; const llarp_buffer_t&,
const llarp_buffer_t&,
const SharedSecret&,
const byte_t*) override;
/// path dh creator's side /// path dh creator's side
bool bool
dh_client(SharedSecret &, const PubKey &, const SecretKey &, dh_client(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&) override;
const TunnelNonce &) override;
/// path dh relay side /// path dh relay side
bool bool
dh_server(SharedSecret &, const PubKey &, const SecretKey &, dh_server(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&) override;
const TunnelNonce &) override;
/// transport dh client side /// transport dh client side
bool bool
transport_dh_client(SharedSecret &, const PubKey &, const SecretKey &, transport_dh_client(
const TunnelNonce &) override; SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&) override;
/// transport dh server side /// transport dh server side
bool bool
transport_dh_server(SharedSecret &, const PubKey &, const SecretKey &, transport_dh_server(
const TunnelNonce &) override; SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&) override;
/// blake2b 256 bit /// blake2b 256 bit
bool bool
shorthash(ShortHash &, const llarp_buffer_t &) override; shorthash(ShortHash&, const llarp_buffer_t&) override;
/// blake2s 256 bit hmac /// blake2s 256 bit hmac
bool bool
hmac(byte_t *, const llarp_buffer_t &, const SharedSecret &) override; hmac(byte_t*, const llarp_buffer_t&, const SharedSecret&) override;
/// ed25519 sign /// ed25519 sign
bool bool
sign(Signature &, const SecretKey &, const llarp_buffer_t &) override; sign(Signature&, const SecretKey&, const llarp_buffer_t&) override;
/// ed25519 sign (custom with derived keys) /// ed25519 sign (custom with derived keys)
bool bool
sign(Signature &, const PrivateKey &, const llarp_buffer_t &) override; sign(Signature&, const PrivateKey&, const llarp_buffer_t&) override;
/// ed25519 verify /// ed25519 verify
bool bool
verify(const PubKey &, const llarp_buffer_t &, verify(const PubKey&, const llarp_buffer_t&, const Signature&) override;
const Signature &) override;
/// derive sub keys for public keys. hash is really only intended for /// derive sub keys for public keys. hash is really only intended for
/// testing and overrides key_n if given. /// testing and overrides key_n if given.
bool bool
derive_subkey(PubKey &derived, const PubKey &root, uint64_t key_n, derive_subkey(
const AlignedBuffer< 32 > *hash = nullptr) override; PubKey& derived,
const PubKey& root,
uint64_t key_n,
const AlignedBuffer<32>* hash = nullptr) override;
/// derive sub keys for private keys. hash is really only intended for /// derive sub keys for private keys. hash is really only intended for
/// testing and overrides key_n if given. /// testing and overrides key_n if given.
bool bool
derive_subkey_private(PrivateKey &derived, const SecretKey &root, derive_subkey_private(
uint64_t key_n, PrivateKey& derived,
const AlignedBuffer< 32 > *hash = nullptr) override; const SecretKey& root,
uint64_t key_n,
const AlignedBuffer<32>* hash = nullptr) override;
/// seed to secretkey /// seed to secretkey
bool bool
seed_to_secretkey(llarp::SecretKey &, seed_to_secretkey(llarp::SecretKey&, const llarp::IdentitySecret&) override;
const llarp::IdentitySecret &) override;
/// randomize buffer /// randomize buffer
void void
randomize(const llarp_buffer_t &) override; randomize(const llarp_buffer_t&) override;
/// randomizer memory /// randomizer memory
void void
randbytes(byte_t *, size_t) override; randbytes(byte_t*, size_t) override;
/// generate signing keypair /// generate signing keypair
void void
identity_keygen(SecretKey &) override; identity_keygen(SecretKey&) override;
/// generate encryption keypair /// generate encryption keypair
void void
encryption_keygen(SecretKey &) override; encryption_keygen(SecretKey&) override;
/// generate post quantum encrytion key /// generate post quantum encrytion key
void void
pqe_keygen(PQKeyPair &) override; pqe_keygen(PQKeyPair&) override;
/// post quantum decrypt (buffer, sharedkey_dst, sec) /// post quantum decrypt (buffer, sharedkey_dst, sec)
bool bool
pqe_decrypt(const PQCipherBlock &, SharedSecret &, pqe_decrypt(const PQCipherBlock&, SharedSecret&, const byte_t*) override;
const byte_t *) override;
/// post quantum encrypt (buffer, sharedkey_dst, pub) /// post quantum encrypt (buffer, sharedkey_dst, pub)
bool bool
pqe_encrypt(PQCipherBlock &, SharedSecret &, const PQPubKey &) override; pqe_encrypt(PQCipherBlock&, SharedSecret&, const PQPubKey&) override;
bool bool
check_identity_privkey(const SecretKey &) override; check_identity_privkey(const SecretKey&) override;
}; };
} // namespace sodium } // namespace sodium

@ -11,9 +11,9 @@ namespace llarp
struct NoOpCrypto final : public Crypto struct NoOpCrypto final : public Crypto
{ {
private: private:
std::atomic< uint64_t > m_value; std::atomic<uint64_t> m_value;
static constexpr byte_t MAX_BYTE = std::numeric_limits< byte_t >::max(); static constexpr byte_t MAX_BYTE = std::numeric_limits<byte_t>::max();
public: public:
NoOpCrypto() : m_value(0) NoOpCrypto() : m_value(0)
@ -23,17 +23,19 @@ namespace llarp
~NoOpCrypto() override = default; ~NoOpCrypto() override = default;
bool bool
xchacha20(const llarp_buffer_t &, const SharedSecret &, xchacha20(const llarp_buffer_t&, const SharedSecret&, const TunnelNonce&) override
const TunnelNonce &) override
{ {
return true; return true;
} }
bool bool
xchacha20_alt(const llarp_buffer_t &out, const llarp_buffer_t &in, xchacha20_alt(
const SharedSecret &, const byte_t *) override const llarp_buffer_t& out,
const llarp_buffer_t& in,
const SharedSecret&,
const byte_t*) override
{ {
if(in.sz > out.sz) if (in.sz > out.sz)
{ {
return false; return false;
} }
@ -43,42 +45,40 @@ namespace llarp
} }
bool bool
dh_client(SharedSecret &shared, const PubKey &pk, const SecretKey &, dh_client(SharedSecret& shared, const PubKey& pk, const SecretKey&, const TunnelNonce&) override
const TunnelNonce &) override
{ {
std::copy_n(pk.begin(), pk.size(), shared.begin()); std::copy_n(pk.begin(), pk.size(), shared.begin());
return true; return true;
} }
bool bool
dh_server(SharedSecret &shared, const PubKey &pk, const SecretKey &, dh_server(SharedSecret& shared, const PubKey& pk, const SecretKey&, const TunnelNonce&) override
const TunnelNonce &) override
{ {
std::copy_n(pk.begin(), pk.size(), shared.begin()); std::copy_n(pk.begin(), pk.size(), shared.begin());
return true; return true;
} }
bool bool
transport_dh_client(SharedSecret &shared, const PubKey &pk, transport_dh_client(
const SecretKey &, const TunnelNonce &) override SharedSecret& shared, const PubKey& pk, const SecretKey&, const TunnelNonce&) override
{ {
std::copy_n(pk.begin(), pk.size(), shared.begin()); std::copy_n(pk.begin(), pk.size(), shared.begin());
return true; return true;
} }
bool bool
transport_dh_server(SharedSecret &shared, const PubKey &pk, transport_dh_server(
const SecretKey &, const TunnelNonce &) override SharedSecret& shared, const PubKey& pk, const SecretKey&, const TunnelNonce&) override
{ {
std::copy_n(pk.begin(), pk.size(), shared.begin()); std::copy_n(pk.begin(), pk.size(), shared.begin());
return true; return true;
} }
bool bool
shorthash(ShortHash &out, const llarp_buffer_t &buff) override shorthash(ShortHash& out, const llarp_buffer_t& buff) override
{ {
// copy the first 32 bytes of the buffer // copy the first 32 bytes of the buffer
if(buff.sz < out.size()) if (buff.sz < out.size())
{ {
std::copy_n(buff.begin(), buff.sz, out.begin()); std::copy_n(buff.begin(), buff.sz, out.begin());
std::fill(out.begin() + buff.sz, out.end(), 0); std::fill(out.begin() + buff.sz, out.end(), 0);
@ -91,9 +91,9 @@ namespace llarp
} }
bool bool
hmac(byte_t *out, const llarp_buffer_t &buff, const SharedSecret &) override hmac(byte_t* out, const llarp_buffer_t& buff, const SharedSecret&) override
{ {
if(buff.sz < HMACSIZE) if (buff.sz < HMACSIZE)
{ {
std::copy_n(buff.begin(), buff.sz, out); std::copy_n(buff.begin(), buff.sz, out);
std::fill(out + buff.sz, out + (HMACSIZE - buff.sz), 0); std::fill(out + buff.sz, out + (HMACSIZE - buff.sz), 0);
@ -106,89 +106,86 @@ namespace llarp
} }
bool bool
sign(Signature &sig, const SecretKey &, const llarp_buffer_t &) override sign(Signature& sig, const SecretKey&, const llarp_buffer_t&) override
{ {
std::fill(sig.begin(), sig.end(), 0); std::fill(sig.begin(), sig.end(), 0);
return true; return true;
} }
bool bool
sign(Signature &sig, const PrivateKey &, const llarp_buffer_t &) override sign(Signature& sig, const PrivateKey&, const llarp_buffer_t&) override
{ {
std::fill(sig.begin(), sig.end(), 0); std::fill(sig.begin(), sig.end(), 0);
return true; return true;
} }
bool bool
verify(const PubKey &, const llarp_buffer_t &, const Signature &) override verify(const PubKey&, const llarp_buffer_t&, const Signature&) override
{ {
return true; return true;
} }
bool bool
seed_to_secretkey(SecretKey &key, const IdentitySecret &secret) override seed_to_secretkey(SecretKey& key, const IdentitySecret& secret) override
{ {
static_assert(SecretKey::SIZE == (2 * IdentitySecret::SIZE), ""); static_assert(SecretKey::SIZE == (2 * IdentitySecret::SIZE), "");
std::copy(secret.begin(), secret.end(), key.begin()); std::copy(secret.begin(), secret.end(), key.begin());
std::copy(secret.begin(), secret.end(), std::copy(secret.begin(), secret.end(), key.begin() + IdentitySecret::SIZE);
key.begin() + IdentitySecret::SIZE);
return true; return true;
} }
void void
randomize(const llarp_buffer_t &buff) override randomize(const llarp_buffer_t& buff) override
{ {
std::iota(buff.begin(), buff.end(), m_value.load() % MAX_BYTE); std::iota(buff.begin(), buff.end(), m_value.load() % MAX_BYTE);
m_value += buff.sz; m_value += buff.sz;
} }
void void
randbytes(byte_t *ptr, size_t sz) override randbytes(byte_t* ptr, size_t sz) override
{ {
std::iota(ptr, ptr + sz, m_value.load() % MAX_BYTE); std::iota(ptr, ptr + sz, m_value.load() % MAX_BYTE);
m_value += sz; m_value += sz;
} }
void void
identity_keygen(SecretKey &key) override identity_keygen(SecretKey& key) override
{ {
std::iota(key.begin(), key.end(), m_value.load() % MAX_BYTE); std::iota(key.begin(), key.end(), m_value.load() % MAX_BYTE);
m_value += key.size(); m_value += key.size();
} }
void void
encryption_keygen(SecretKey &key) override encryption_keygen(SecretKey& key) override
{ {
std::iota(key.begin(), key.end(), m_value.load() % MAX_BYTE); std::iota(key.begin(), key.end(), m_value.load() % MAX_BYTE);
m_value += key.size(); m_value += key.size();
} }
void void
pqe_keygen(PQKeyPair &pair) override pqe_keygen(PQKeyPair& pair) override
{ {
std::iota(pair.begin(), pair.end(), m_value.load() % MAX_BYTE); std::iota(pair.begin(), pair.end(), m_value.load() % MAX_BYTE);
m_value += pair.size(); m_value += pair.size();
} }
bool bool
pqe_decrypt(const PQCipherBlock &block, SharedSecret &secret, pqe_decrypt(const PQCipherBlock& block, SharedSecret& secret, const byte_t*) override
const byte_t *) override
{ {
std::copy_n(block.begin(), SharedSecret::SIZE, secret.begin()); std::copy_n(block.begin(), SharedSecret::SIZE, secret.begin());
return true; return true;
} }
bool bool
pqe_encrypt(PQCipherBlock &block, SharedSecret &secret, pqe_encrypt(PQCipherBlock& block, SharedSecret& secret, const PQPubKey&) override
const PQPubKey &) override
{ {
std::copy_n(secret.begin(), SharedSecret::SIZE, block.begin()); std::copy_n(secret.begin(), SharedSecret::SIZE, block.begin());
return true; return true;
} }
bool bool
check_identity_privkey(const SecretKey &) override check_identity_privkey(const SecretKey&) override
{ {
return true; return true;
} }

@ -13,12 +13,12 @@
namespace llarp namespace llarp
{ {
/// encrypted buffer base type /// encrypted buffer base type
template < size_t bufsz = MAX_LINK_MSG_SIZE > template <size_t bufsz = MAX_LINK_MSG_SIZE>
struct Encrypted struct Encrypted
{ {
Encrypted(Encrypted&& other) Encrypted(Encrypted&& other)
{ {
_sz = std::move(other._sz); _sz = std::move(other._sz);
_buf = std::move(other._buf); _buf = std::move(other._buf);
UpdateBuffer(); UpdateBuffer();
} }
@ -42,10 +42,10 @@ namespace llarp
Encrypted(const byte_t* buf, size_t sz) Encrypted(const byte_t* buf, size_t sz)
{ {
if(sz <= bufsz) if (sz <= bufsz)
{ {
_sz = sz; _sz = sz;
if(buf) if (buf)
memcpy(_buf.data(), buf, sz); memcpy(_buf.data(), buf, sz);
else else
_buf.Zero(); _buf.Zero();
@ -86,7 +86,7 @@ namespace llarp
Encrypted& Encrypted&
operator=(const llarp_buffer_t& buf) operator=(const llarp_buffer_t& buf)
{ {
if(buf.sz <= _buf.size()) if (buf.sz <= _buf.size())
{ {
_sz = buf.sz; _sz = buf.sz;
memcpy(_buf.data(), buf.base, _sz); memcpy(_buf.data(), buf.base, _sz);
@ -104,7 +104,7 @@ namespace llarp
void void
Randomize() Randomize()
{ {
if(_sz) if (_sz)
randombytes(_buf.data(), _sz); randombytes(_buf.data(), _sz);
} }
@ -112,12 +112,12 @@ namespace llarp
BDecode(llarp_buffer_t* buf) BDecode(llarp_buffer_t* buf)
{ {
llarp_buffer_t strbuf; llarp_buffer_t strbuf;
if(!bencode_read_string(buf, &strbuf)) if (!bencode_read_string(buf, &strbuf))
return false; return false;
if(strbuf.sz > sizeof(_buf)) if (strbuf.sz > sizeof(_buf))
return false; return false;
_sz = strbuf.sz; _sz = strbuf.sz;
if(_sz) if (_sz)
memcpy(_buf.data(), strbuf.base, _sz); memcpy(_buf.data(), strbuf.base, _sz);
UpdateBuffer(); UpdateBuffer();
return true; return true;
@ -158,10 +158,10 @@ namespace llarp
UpdateBuffer() UpdateBuffer()
{ {
m_Buffer.base = _buf.data(); m_Buffer.base = _buf.data();
m_Buffer.cur = _buf.data(); m_Buffer.cur = _buf.data();
m_Buffer.sz = _sz; m_Buffer.sz = _sz;
} }
AlignedBuffer< bufsz > _buf; AlignedBuffer<bufsz> _buf;
size_t _sz; size_t _sz;
llarp_buffer_t m_Buffer; llarp_buffer_t m_Buffer;
}; // namespace llarp }; // namespace llarp

@ -9,17 +9,17 @@ namespace llarp
bool bool
EncryptedFrame::DoEncrypt(const SharedSecret& shared, bool noDH) EncryptedFrame::DoEncrypt(const SharedSecret& shared, bool noDH)
{ {
byte_t* hash = data(); byte_t* hash = data();
byte_t* noncePtr = hash + SHORTHASHSIZE; byte_t* noncePtr = hash + SHORTHASHSIZE;
byte_t* pubkey = noncePtr + TUNNONCESIZE; byte_t* pubkey = noncePtr + TUNNONCESIZE;
byte_t* body = pubkey + PUBKEYSIZE; byte_t* body = pubkey + PUBKEYSIZE;
auto crypto = CryptoManager::instance(); auto crypto = CryptoManager::instance();
// if noDH flag, means key exchange has already taken place // if noDH flag, means key exchange has already taken place
// in this case, set pubkey to random noise and choose a // in this case, set pubkey to random noise and choose a
// random nonce here // random nonce here
if(noDH) if (noDH)
{ {
crypto->randbytes(noncePtr, TUNNONCESIZE); crypto->randbytes(noncePtr, TUNNONCESIZE);
crypto->randbytes(pubkey, PUBKEYSIZE); crypto->randbytes(pubkey, PUBKEYSIZE);
@ -29,11 +29,11 @@ namespace llarp
llarp_buffer_t buf; llarp_buffer_t buf;
buf.base = body; buf.base = body;
buf.cur = buf.base; buf.cur = buf.base;
buf.sz = size() - EncryptedFrameOverheadSize; buf.sz = size() - EncryptedFrameOverheadSize;
// encrypt body // encrypt body
if(!crypto->xchacha20(buf, shared, nonce)) if (!crypto->xchacha20(buf, shared, nonce))
{ {
llarp::LogError("encrypt failed"); llarp::LogError("encrypt failed");
return false; return false;
@ -41,10 +41,10 @@ namespace llarp
// generate message auth // generate message auth
buf.base = noncePtr; buf.base = noncePtr;
buf.cur = buf.base; buf.cur = buf.base;
buf.sz = size() - SHORTHASHSIZE; buf.sz = size() - SHORTHASHSIZE;
if(!crypto->hmac(hash, buf, shared)) if (!crypto->hmac(hash, buf, shared))
{ {
llarp::LogError("Failed to generate message auth"); llarp::LogError("Failed to generate message auth");
return false; return false;
@ -54,8 +54,7 @@ namespace llarp
} }
bool bool
EncryptedFrame::EncryptInPlace(const SecretKey& ourSecretKey, EncryptedFrame::EncryptInPlace(const SecretKey& ourSecretKey, const PubKey& otherPubkey)
const PubKey& otherPubkey)
{ {
// format of frame is // format of frame is
// <32 bytes keyed hash of following data> // <32 bytes keyed hash of following data>
@ -63,9 +62,9 @@ namespace llarp
// <32 bytes pubkey> // <32 bytes pubkey>
// <N bytes encrypted payload> // <N bytes encrypted payload>
// //
byte_t* hash = data(); byte_t* hash = data();
byte_t* noncePtr = hash + SHORTHASHSIZE; byte_t* noncePtr = hash + SHORTHASHSIZE;
byte_t* pubkey = noncePtr + TUNNONCESIZE; byte_t* pubkey = noncePtr + TUNNONCESIZE;
SharedSecret shared; SharedSecret shared;
@ -78,7 +77,7 @@ namespace llarp
TunnelNonce nonce(noncePtr); TunnelNonce nonce(noncePtr);
// derive shared key // derive shared key
if(!crypto->dh_client(shared, otherPubkey, ourSecretKey, nonce)) if (!crypto->dh_client(shared, otherPubkey, ourSecretKey, nonce))
{ {
llarp::LogError("DH failed"); llarp::LogError("DH failed");
return false; return false;
@ -92,34 +91,34 @@ namespace llarp
{ {
ShortHash hash(data()); ShortHash hash(data());
byte_t* noncePtr = data() + SHORTHASHSIZE; byte_t* noncePtr = data() + SHORTHASHSIZE;
byte_t* body = data() + EncryptedFrameOverheadSize; byte_t* body = data() + EncryptedFrameOverheadSize;
TunnelNonce nonce(noncePtr); TunnelNonce nonce(noncePtr);
auto crypto = CryptoManager::instance(); auto crypto = CryptoManager::instance();
llarp_buffer_t buf; llarp_buffer_t buf;
buf.base = noncePtr; buf.base = noncePtr;
buf.cur = buf.base; buf.cur = buf.base;
buf.sz = size() - SHORTHASHSIZE; buf.sz = size() - SHORTHASHSIZE;
ShortHash digest; ShortHash digest;
if(!crypto->hmac(digest.data(), buf, shared)) if (!crypto->hmac(digest.data(), buf, shared))
{ {
llarp::LogError("Digest failed"); llarp::LogError("Digest failed");
return false; return false;
} }
if(!std::equal(digest.begin(), digest.end(), hash.begin())) if (!std::equal(digest.begin(), digest.end(), hash.begin()))
{ {
llarp::LogError("message authentication failed"); llarp::LogError("message authentication failed");
return false; return false;
} }
buf.base = body; buf.base = body;
buf.cur = body; buf.cur = body;
buf.sz = size() - EncryptedFrameOverheadSize; buf.sz = size() - EncryptedFrameOverheadSize;
if(!crypto->xchacha20(buf, shared, nonce)) if (!crypto->xchacha20(buf, shared, nonce))
{ {
llarp::LogError("decrypt failed"); llarp::LogError("decrypt failed");
return false; return false;
@ -146,7 +145,7 @@ namespace llarp
auto crypto = CryptoManager::instance(); auto crypto = CryptoManager::instance();
// use dh_server because we are not the creator of this message // use dh_server because we are not the creator of this message
if(!crypto->dh_server(shared, otherPubkey, ourSecretKey, nonce)) if (!crypto->dh_server(shared, otherPubkey, ourSecretKey, nonce))
{ {
llarp::LogError("DH failed"); llarp::LogError("DH failed");
return false; return false;

@ -10,28 +10,26 @@
namespace llarp namespace llarp
{ {
static constexpr size_t EncryptedFrameOverheadSize = static constexpr size_t EncryptedFrameOverheadSize = PUBKEYSIZE + TUNNONCESIZE + SHORTHASHSIZE;
PUBKEYSIZE + TUNNONCESIZE + SHORTHASHSIZE;
static constexpr size_t EncryptedFrameBodySize = 128 * 6; static constexpr size_t EncryptedFrameBodySize = 128 * 6;
static constexpr size_t EncryptedFrameSize = static constexpr size_t EncryptedFrameSize = EncryptedFrameOverheadSize + EncryptedFrameBodySize;
EncryptedFrameOverheadSize + EncryptedFrameBodySize;
struct EncryptedFrame : public Encrypted< EncryptedFrameSize > struct EncryptedFrame : public Encrypted<EncryptedFrameSize>
{ {
EncryptedFrame() : EncryptedFrame(EncryptedFrameBodySize) EncryptedFrame() : EncryptedFrame(EncryptedFrameBodySize)
{ {
} }
EncryptedFrame(size_t sz) EncryptedFrame(size_t sz)
: Encrypted< EncryptedFrameSize >(std::min(sz, EncryptedFrameBodySize) : Encrypted<EncryptedFrameSize>(
+ EncryptedFrameOverheadSize) std::min(sz, EncryptedFrameBodySize) + EncryptedFrameOverheadSize)
{ {
} }
void void
Resize(size_t sz) Resize(size_t sz)
{ {
if(sz <= EncryptedFrameSize) if (sz <= EncryptedFrameSize)
{ {
_sz = sz; _sz = sz;
UpdateBuffer(); UpdateBuffer();
@ -52,16 +50,16 @@ namespace llarp
}; };
/// TODO: can only handle 1 frame at a time /// TODO: can only handle 1 frame at a time
template < typename User > template <typename User>
struct AsyncFrameDecrypter struct AsyncFrameDecrypter
{ {
using User_ptr = std::shared_ptr< User >; using User_ptr = std::shared_ptr<User>;
using DecryptHandler = std::function< void(llarp_buffer_t*, User_ptr) >; using DecryptHandler = std::function<void(llarp_buffer_t*, User_ptr)>;
void void
Decrypt(User_ptr user) Decrypt(User_ptr user)
{ {
if(target.DecryptInPlace(seckey)) if (target.DecryptInPlace(seckey))
{ {
auto buf = target.Buffer(); auto buf = target.Buffer();
buf->cur = buf->base + EncryptedFrameOverheadSize; buf->cur = buf->base + EncryptedFrameOverheadSize;
@ -81,12 +79,11 @@ namespace llarp
EncryptedFrame target; EncryptedFrame target;
void void
AsyncDecrypt(const std::shared_ptr< thread::ThreadPool >& worker, AsyncDecrypt(
const EncryptedFrame& frame, User_ptr u) const std::shared_ptr<thread::ThreadPool>& worker, const EncryptedFrame& frame, User_ptr u)
{ {
target = frame; target = frame;
worker->addJob( worker->addJob(std::bind(&AsyncFrameDecrypter<User>::Decrypt, this, std::move(u)));
std::bind(&AsyncFrameDecrypter< User >::Decrypt, this, std::move(u)));
} }
}; };
} // namespace llarp } // namespace llarp

@ -30,7 +30,7 @@ namespace llarp
SecretKey::LoadFromFile(const char* fname) SecretKey::LoadFromFile(const char* fname)
{ {
std::ifstream f(fname, std::ios::in | std::ios::binary); std::ifstream f(fname, std::ios::in | std::ios::binary);
if(!f.is_open()) if (!f.is_open())
{ {
return false; return false;
} }
@ -39,19 +39,19 @@ namespace llarp
const size_t sz = f.tellg(); const size_t sz = f.tellg();
f.seekg(0, std::ios::beg); f.seekg(0, std::ios::beg);
if(sz == size()) if (sz == size())
{ {
// is raw buffer // is raw buffer
std::copy_n(std::istreambuf_iterator< char >(f), sz, begin()); std::copy_n(std::istreambuf_iterator<char>(f), sz, begin());
return true; return true;
} }
std::array< byte_t, 128 > tmp; std::array<byte_t, 128> tmp;
llarp_buffer_t buf(tmp); llarp_buffer_t buf(tmp);
if(sz > sizeof(tmp)) if (sz > sizeof(tmp))
{ {
return false; return false;
} }
f.read(reinterpret_cast< char* >(tmp.data()), sz); f.read(reinterpret_cast<char*>(tmp.data()), sz);
return BDecode(&buf); return BDecode(&buf);
} }
@ -60,7 +60,7 @@ namespace llarp
{ {
PrivateKey key; PrivateKey key;
PubKey pubkey; PubKey pubkey;
if(!toPrivate(key) || !key.toPublic(pubkey)) if (!toPrivate(key) || !key.toPublic(pubkey))
return false; return false;
std::memcpy(data() + 32, pubkey.data(), 32); std::memcpy(data() + 32, pubkey.data(), 32);
return true; return true;
@ -73,7 +73,7 @@ namespace llarp
// is the private key; the second half is the hash that gets used in // is the private key; the second half is the hash that gets used in
// signing. // signing.
unsigned char h[crypto_hash_sha512_BYTES]; unsigned char h[crypto_hash_sha512_BYTES];
if(crypto_hash_sha512(h, data(), 32) < 0) if (crypto_hash_sha512(h, data(), 32) < 0)
return false; return false;
h[0] &= 248; h[0] &= 248;
h[31] &= 63; h[31] &= 63;
@ -91,19 +91,18 @@ namespace llarp
bool bool
SecretKey::SaveToFile(const char* fname) const SecretKey::SaveToFile(const char* fname) const
{ {
std::array< byte_t, 128 > tmp; std::array<byte_t, 128> tmp;
llarp_buffer_t buf(tmp); llarp_buffer_t buf(tmp);
if(!BEncode(&buf)) if (!BEncode(&buf))
{ {
return false; return false;
} }
const fs::path fpath = std::string(fname); const fs::path fpath = std::string(fname);
auto optional_f = auto optional_f = llarp::util::OpenFileStream<std::ofstream>(fpath, std::ios::binary);
llarp::util::OpenFileStream< std::ofstream >(fpath, std::ios::binary); if (!optional_f)
if(!optional_f)
return false; return false;
auto& f = optional_f.value(); auto& f = optional_f.value();
if(!f.is_open()) if (!f.is_open())
return false; return false;
f.write((char*)buf.base, buf.cur - buf.base); f.write((char*)buf.base, buf.cur - buf.base);
return f.good(); return f.good();
@ -113,20 +112,19 @@ namespace llarp
IdentitySecret::LoadFromFile(const char* fname) IdentitySecret::LoadFromFile(const char* fname)
{ {
const fs::path fpath = std::string(fname); const fs::path fpath = std::string(fname);
auto optional = util::OpenFileStream< std::ifstream >( auto optional = util::OpenFileStream<std::ifstream>(fpath, std::ios::binary | std::ios::in);
fpath, std::ios::binary | std::ios::in); if (!optional)
if(!optional)
return false; return false;
auto& f = optional.value(); auto& f = optional.value();
f.seekg(0, std::ios::end); f.seekg(0, std::ios::end);
const size_t sz = f.tellg(); const size_t sz = f.tellg();
f.seekg(0, std::ios::beg); f.seekg(0, std::ios::beg);
if(sz != 32) if (sz != 32)
{ {
llarp::LogError("service node seed size invalid: ", sz, " != 32"); llarp::LogError("service node seed size invalid: ", sz, " != 32");
return false; return false;
} }
std::copy_n(std::istreambuf_iterator< char >(f), sz, begin()); std::copy_n(std::istreambuf_iterator<char>(f), sz, begin());
return true; return true;
} }

@ -11,23 +11,22 @@
namespace llarp namespace llarp
{ {
using SharedSecret = AlignedBuffer< SHAREDKEYSIZE >; using SharedSecret = AlignedBuffer<SHAREDKEYSIZE>;
using KeyExchangeNonce = AlignedBuffer< 32 >; using KeyExchangeNonce = AlignedBuffer<32>;
struct PubKey final : public AlignedBuffer< PUBKEYSIZE > struct PubKey final : public AlignedBuffer<PUBKEYSIZE>
{ {
PubKey() = default; PubKey() = default;
explicit PubKey(const byte_t *ptr) : AlignedBuffer< SIZE >(ptr) explicit PubKey(const byte_t* ptr) : AlignedBuffer<SIZE>(ptr)
{ {
} }
explicit PubKey(const Data &data) : AlignedBuffer< SIZE >(data) explicit PubKey(const Data& data) : AlignedBuffer<SIZE>(data)
{ {
} }
explicit PubKey(const AlignedBuffer< SIZE > &other) explicit PubKey(const AlignedBuffer<SIZE>& other) : AlignedBuffer<SIZE>(other)
: AlignedBuffer< SIZE >(other)
{ {
} }
@ -35,41 +34,41 @@ namespace llarp
ToString() const; ToString() const;
bool bool
FromString(const std::string &str); FromString(const std::string& str);
operator RouterID() const operator RouterID() const
{ {
return RouterID(as_array()); return RouterID(as_array());
} }
PubKey & PubKey&
operator=(const byte_t *ptr) operator=(const byte_t* ptr)
{ {
std::copy(ptr, ptr + SIZE, begin()); std::copy(ptr, ptr + SIZE, begin());
return *this; return *this;
} }
}; };
inline std::ostream & inline std::ostream&
operator<<(std::ostream &out, const PubKey &k) operator<<(std::ostream& out, const PubKey& k)
{ {
return out << k.ToString(); return out << k.ToString();
} }
inline bool inline bool
operator==(const PubKey &lhs, const PubKey &rhs) operator==(const PubKey& lhs, const PubKey& rhs)
{ {
return lhs.as_array() == rhs.as_array(); return lhs.as_array() == rhs.as_array();
} }
inline bool inline bool
operator==(const PubKey &lhs, const RouterID &rhs) operator==(const PubKey& lhs, const RouterID& rhs)
{ {
return lhs.as_array() == rhs.as_array(); return lhs.as_array() == rhs.as_array();
} }
inline bool inline bool
operator==(const RouterID &lhs, const PubKey &rhs) operator==(const RouterID& lhs, const PubKey& rhs)
{ {
return lhs.as_array() == rhs.as_array(); return lhs.as_array() == rhs.as_array();
} }
@ -79,22 +78,21 @@ namespace llarp
/// Stores a sodium "secret key" value, which is actually the seed /// Stores a sodium "secret key" value, which is actually the seed
/// concatenated with the public key. Note that the seed is *not* the private /// concatenated with the public key. Note that the seed is *not* the private
/// key value itself, but rather the seed from which it can be calculated. /// key value itself, but rather the seed from which it can be calculated.
struct SecretKey final : public AlignedBuffer< SECKEYSIZE > struct SecretKey final : public AlignedBuffer<SECKEYSIZE>
{ {
SecretKey() = default; SecretKey() = default;
explicit SecretKey(const byte_t *ptr) : AlignedBuffer< SECKEYSIZE >(ptr) explicit SecretKey(const byte_t* ptr) : AlignedBuffer<SECKEYSIZE>(ptr)
{ {
} }
// The full data // The full data
explicit SecretKey(const AlignedBuffer< SECKEYSIZE > &seed) explicit SecretKey(const AlignedBuffer<SECKEYSIZE>& seed) : AlignedBuffer<SECKEYSIZE>(seed)
: AlignedBuffer< SECKEYSIZE >(seed)
{ {
} }
// Just the seed, we recalculate the pubkey // Just the seed, we recalculate the pubkey
explicit SecretKey(const AlignedBuffer< 32 > &seed) explicit SecretKey(const AlignedBuffer<32>& seed)
{ {
std::copy(seed.begin(), seed.end(), begin()); std::copy(seed.begin(), seed.end(), begin());
Recalculate(); Recalculate();
@ -104,8 +102,8 @@ namespace llarp
bool bool
Recalculate(); Recalculate();
std::ostream & std::ostream&
print(std::ostream &stream, int level, int spaces) const print(std::ostream& stream, int level, int spaces) const
{ {
Printer printer(stream, level, spaces); Printer printer(stream, level, spaces);
printer.printValue("secretkey"); printer.printValue("secretkey");
@ -121,17 +119,17 @@ namespace llarp
/// Computes the private key from the secret key (which is actually the /// Computes the private key from the secret key (which is actually the
/// seed) /// seed)
bool bool
toPrivate(PrivateKey &key) const; toPrivate(PrivateKey& key) const;
bool bool
LoadFromFile(const char *fname); LoadFromFile(const char* fname);
bool bool
SaveToFile(const char *fname) const; SaveToFile(const char* fname) const;
}; };
inline std::ostream & inline std::ostream&
operator<<(std::ostream &out, const SecretKey &) operator<<(std::ostream& out, const SecretKey&)
{ {
// return out << k.ToHex(); // return out << k.ToHex();
// make sure we never print out secret keys // make sure we never print out secret keys
@ -143,22 +141,21 @@ namespace llarp
/// the private key and hash value are generated. This is primarily intended /// the private key and hash value are generated. This is primarily intended
/// for use with derived keys, where we can derive the private key but not the /// for use with derived keys, where we can derive the private key but not the
/// seed. /// seed.
struct PrivateKey final : public AlignedBuffer< 64 > struct PrivateKey final : public AlignedBuffer<64>
{ {
PrivateKey() = default; PrivateKey() = default;
explicit PrivateKey(const byte_t *ptr) : AlignedBuffer< 64 >(ptr) explicit PrivateKey(const byte_t* ptr) : AlignedBuffer<64>(ptr)
{ {
} }
explicit PrivateKey(const AlignedBuffer< 64 > &key_and_hash) explicit PrivateKey(const AlignedBuffer<64>& key_and_hash) : AlignedBuffer<64>(key_and_hash)
: AlignedBuffer< 64 >(key_and_hash)
{ {
} }
/// Returns a pointer to the beginning of the 32-byte hash which is used for /// Returns a pointer to the beginning of the 32-byte hash which is used for
/// pseudorandomness when signing with this private key. /// pseudorandomness when signing with this private key.
const byte_t * const byte_t*
signingHash() const signingHash() const
{ {
return data() + 32; return data() + 32;
@ -166,14 +163,14 @@ namespace llarp
/// Returns a pointer to the beginning of the 32-byte hash which is used for /// Returns a pointer to the beginning of the 32-byte hash which is used for
/// pseudorandomness when signing with this private key. /// pseudorandomness when signing with this private key.
byte_t * byte_t*
signingHash() signingHash()
{ {
return data() + 32; return data() + 32;
} }
std::ostream & std::ostream&
print(std::ostream &stream, int level, int spaces) const print(std::ostream& stream, int level, int spaces) const
{ {
Printer printer(stream, level, spaces); Printer printer(stream, level, spaces);
printer.printValue("privatekey"); printer.printValue("privatekey");
@ -182,11 +179,11 @@ namespace llarp
/// Computes the public key /// Computes the public key
bool bool
toPublic(PubKey &pubkey) const; toPublic(PubKey& pubkey) const;
}; };
inline std::ostream & inline std::ostream&
operator<<(std::ostream &out, const PrivateKey &) operator<<(std::ostream& out, const PrivateKey&)
{ {
// return out << k.ToHex(); // return out << k.ToHex();
// make sure we never print out private keys // make sure we never print out private keys
@ -194,66 +191,65 @@ namespace llarp
} }
/// IdentitySecret is a secret key from a service node secret seed /// IdentitySecret is a secret key from a service node secret seed
struct IdentitySecret final : public AlignedBuffer< 32 > struct IdentitySecret final : public AlignedBuffer<32>
{ {
IdentitySecret() : AlignedBuffer< 32 >() IdentitySecret() : AlignedBuffer<32>()
{ {
} }
/// no copy constructor /// no copy constructor
explicit IdentitySecret(const IdentitySecret &) = delete; explicit IdentitySecret(const IdentitySecret&) = delete;
// no byte data constructor // no byte data constructor
explicit IdentitySecret(const byte_t *) = delete; explicit IdentitySecret(const byte_t*) = delete;
/// load service node seed from file /// load service node seed from file
bool bool
LoadFromFile(const char *fname); LoadFromFile(const char* fname);
}; };
inline std::ostream & inline std::ostream&
operator<<(std::ostream &out, const IdentitySecret &) operator<<(std::ostream& out, const IdentitySecret&)
{ {
// make sure we never print out secret keys // make sure we never print out secret keys
return out << "[IdentitySecret]"; return out << "[IdentitySecret]";
} }
using ShortHash = AlignedBuffer< SHORTHASHSIZE >; using ShortHash = AlignedBuffer<SHORTHASHSIZE>;
using LongHash = AlignedBuffer< HASHSIZE >; using LongHash = AlignedBuffer<HASHSIZE>;
struct Signature final : public AlignedBuffer< SIGSIZE > struct Signature final : public AlignedBuffer<SIGSIZE>
{ {
byte_t * byte_t*
Hi(); Hi();
const byte_t * const byte_t*
Hi() const; Hi() const;
byte_t * byte_t*
Lo(); Lo();
const byte_t * const byte_t*
Lo() const; Lo() const;
}; };
using TunnelNonce = AlignedBuffer< TUNNONCESIZE >; using TunnelNonce = AlignedBuffer<TUNNONCESIZE>;
using SymmNonce = AlignedBuffer< NONCESIZE >; using SymmNonce = AlignedBuffer<NONCESIZE>;
using SymmKey = AlignedBuffer< 32 >; using SymmKey = AlignedBuffer<32>;
using PQCipherBlock = AlignedBuffer< PQ_CIPHERTEXTSIZE + 1 >; using PQCipherBlock = AlignedBuffer<PQ_CIPHERTEXTSIZE + 1>;
using PQPubKey = AlignedBuffer< PQ_PUBKEYSIZE >; using PQPubKey = AlignedBuffer<PQ_PUBKEYSIZE>;
using PQKeyPair = AlignedBuffer< PQ_KEYPAIRSIZE >; using PQKeyPair = AlignedBuffer<PQ_KEYPAIRSIZE>;
/// PKE(result, publickey, secretkey, nonce) /// PKE(result, publickey, secretkey, nonce)
using path_dh_func = std::function< bool( using path_dh_func =
SharedSecret &, const PubKey &, const SecretKey &, const TunnelNonce &) >; std::function<bool(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&)>;
/// TKE(result, publickey, secretkey, nonce) /// TKE(result, publickey, secretkey, nonce)
using transport_dh_func = std::function< bool( using transport_dh_func =
SharedSecret &, const PubKey &, const SecretKey &, const TunnelNonce &) >; std::function<bool(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&)>;
/// SH(result, body) /// SH(result, body)
using shorthash_func = using shorthash_func = std::function<bool(ShortHash&, const llarp_buffer_t&)>;
std::function< bool(ShortHash &, const llarp_buffer_t &) >;
} // namespace llarp } // namespace llarp
#endif #endif

@ -13,14 +13,13 @@ namespace llarp
{ {
namespace dht namespace dht
{ {
template < typename Val_t > template <typename Val_t>
struct Bucket struct Bucket
{ {
using BucketStorage_t = std::map< Key_t, Val_t, XorMetric >; using BucketStorage_t = std::map<Key_t, Val_t, XorMetric>;
using Random_t = std::function< uint64_t() >; using Random_t = std::function<uint64_t()>;
Bucket(const Key_t& us, Random_t r) Bucket(const Key_t& us, Random_t r) : nodes(XorMetric(us)), random(std::move(r))
: nodes(XorMetric(us)), random(std::move(r))
{ {
} }
@ -28,7 +27,7 @@ namespace llarp
ExtractStatus() const ExtractStatus() const
{ {
util::StatusObject obj{}; util::StatusObject obj{};
for(const auto& item : nodes) for (const auto& item : nodes)
{ {
obj[item.first.ToString()] = item.second.ExtractStatus(); obj[item.first.ToString()] = item.second.ExtractStatus();
} }
@ -44,30 +43,31 @@ namespace llarp
struct SetIntersector struct SetIntersector
{ {
bool bool
operator()(const typename BucketStorage_t::value_type& lhs, operator()(const typename BucketStorage_t::value_type& lhs, const Key_t& rhs)
const Key_t& rhs)
{ {
return lhs.first < rhs; return lhs.first < rhs;
} }
bool bool
operator()(const Key_t& lhs, operator()(const Key_t& lhs, const typename BucketStorage_t::value_type& rhs)
const typename BucketStorage_t::value_type& rhs)
{ {
return lhs < rhs.first; return lhs < rhs.first;
} }
}; };
bool bool
GetRandomNodeExcluding(Key_t& result, GetRandomNodeExcluding(Key_t& result, const std::set<Key_t>& exclude) const
const std::set< Key_t >& exclude) const
{ {
std::vector< typename BucketStorage_t::value_type > candidates; std::vector<typename BucketStorage_t::value_type> candidates;
std::set_difference(nodes.begin(), nodes.end(), exclude.begin(), std::set_difference(
exclude.end(), std::back_inserter(candidates), nodes.begin(),
SetIntersector()); nodes.end(),
exclude.begin(),
if(candidates.empty()) exclude.end(),
std::back_inserter(candidates),
SetIntersector());
if (candidates.empty())
{ {
return false; return false;
} }
@ -80,42 +80,42 @@ namespace llarp
{ {
Key_t mindist; Key_t mindist;
mindist.Fill(0xff); mindist.Fill(0xff);
for(const auto& item : nodes) for (const auto& item : nodes)
{ {
auto curDist = item.first ^ target; auto curDist = item.first ^ target;
if(curDist < mindist) if (curDist < mindist)
{ {
mindist = curDist; mindist = curDist;
result = item.first; result = item.first;
} }
} }
return nodes.size() > 0; return nodes.size() > 0;
} }
bool bool
GetManyRandom(std::set< Key_t >& result, size_t N) const GetManyRandom(std::set<Key_t>& result, size_t N) const
{ {
if(nodes.size() < N || nodes.empty()) if (nodes.size() < N || nodes.empty())
{ {
llarp::LogWarn("Not enough dht nodes, have ", nodes.size(), " want ", llarp::LogWarn("Not enough dht nodes, have ", nodes.size(), " want ", N);
N);
return false; return false;
} }
if(nodes.size() == N) if (nodes.size() == N)
{ {
std::transform(nodes.begin(), nodes.end(), std::transform(
std::inserter(result, result.end()), nodes.begin(), nodes.end(), std::inserter(result, result.end()), [](const auto& a) {
[](const auto& a) { return a.first; }); return a.first;
});
return true; return true;
} }
size_t expecting = N; size_t expecting = N;
size_t sz = nodes.size(); size_t sz = nodes.size();
while(N) while (N)
{ {
auto itr = nodes.begin(); auto itr = nodes.begin();
std::advance(itr, random() % sz); std::advance(itr, random() % sz);
if(result.insert(itr->first).second) if (result.insert(itr->first).second)
{ {
--N; --N;
} }
@ -124,40 +124,42 @@ namespace llarp
} }
bool bool
FindCloseExcluding(const Key_t& target, Key_t& result, FindCloseExcluding(const Key_t& target, Key_t& result, const std::set<Key_t>& exclude) const
const std::set< Key_t >& exclude) const
{ {
Key_t maxdist; Key_t maxdist;
maxdist.Fill(0xff); maxdist.Fill(0xff);
Key_t mindist; Key_t mindist;
mindist.Fill(0xff); mindist.Fill(0xff);
for(const auto& item : nodes) for (const auto& item : nodes)
{ {
if(exclude.count(item.first)) if (exclude.count(item.first))
{ {
continue; continue;
} }
auto curDist = item.first ^ target; auto curDist = item.first ^ target;
if(curDist < mindist) if (curDist < mindist)
{ {
mindist = curDist; mindist = curDist;
result = item.first; result = item.first;
} }
} }
return mindist < maxdist; return mindist < maxdist;
} }
bool bool
GetManyNearExcluding(const Key_t& target, std::set< Key_t >& result, GetManyNearExcluding(
size_t N, const std::set< Key_t >& exclude) const const Key_t& target,
std::set<Key_t>& result,
size_t N,
const std::set<Key_t>& exclude) const
{ {
std::set< Key_t > s(exclude.begin(), exclude.end()); std::set<Key_t> s(exclude.begin(), exclude.end());
Key_t peer; Key_t peer;
while(N--) while (N--)
{ {
if(!FindCloseExcluding(target, peer, s)) if (!FindCloseExcluding(target, peer, s))
{ {
return false; return false;
} }
@ -171,7 +173,7 @@ namespace llarp
PutNode(const Val_t& val) PutNode(const Val_t& val)
{ {
auto itr = nodes.find(val.ID); auto itr = nodes.find(val.ID);
if(itr == nodes.end() || itr->second < val) if (itr == nodes.end() || itr->second < val)
{ {
nodes[val.ID] = val; nodes[val.ID] = val;
} }
@ -181,7 +183,7 @@ namespace llarp
DelNode(const Key_t& key) DelNode(const Key_t& key)
{ {
auto itr = nodes.find(key); auto itr = nodes.find(key);
if(itr != nodes.end()) if (itr != nodes.end())
{ {
nodes.erase(itr); nodes.erase(itr);
} }
@ -194,25 +196,25 @@ namespace llarp
} }
// remove all nodes who's key matches a predicate // remove all nodes who's key matches a predicate
template < typename Predicate > template <typename Predicate>
void void
RemoveIf(Predicate pred) RemoveIf(Predicate pred)
{ {
auto itr = nodes.begin(); auto itr = nodes.begin();
while(itr != nodes.end()) while (itr != nodes.end())
{ {
if(pred(itr->first)) if (pred(itr->first))
itr = nodes.erase(itr); itr = nodes.erase(itr);
else else
++itr; ++itr;
} }
} }
template < typename Visit_t > template <typename Visit_t>
void void
ForEachNode(Visit_t visit) ForEachNode(Visit_t visit)
{ {
for(const auto& item : nodes) for (const auto& item : nodes)
{ {
visit(item.second); visit(item.second);
} }

@ -47,28 +47,36 @@ namespace llarp
void void
LookupIntroSetRelayed( LookupIntroSetRelayed(
const Key_t& target, const Key_t& whoasked, uint64_t whoaskedTX, const Key_t& target,
const Key_t& askpeer, uint64_t relayOrder, const Key_t& whoasked,
uint64_t whoaskedTX,
const Key_t& askpeer,
uint64_t relayOrder,
service::EncryptedIntroSetLookupHandler result = nullptr) override; service::EncryptedIntroSetLookupHandler result = nullptr) override;
void void
LookupIntroSetDirect( LookupIntroSetDirect(
const Key_t& target, const Key_t& whoasked, uint64_t whoaskedTX, const Key_t& target,
const Key_t& whoasked,
uint64_t whoaskedTX,
const Key_t& askpeer, const Key_t& askpeer,
service::EncryptedIntroSetLookupHandler result = nullptr) override; service::EncryptedIntroSetLookupHandler result = nullptr) override;
/// on behalf of whoasked request router with public key target from dht /// on behalf of whoasked request router with public key target from dht
/// router with key askpeer /// router with key askpeer
void void
LookupRouterRecursive(const RouterID& target, const Key_t& whoasked, LookupRouterRecursive(
uint64_t whoaskedTX, const Key_t& askpeer, const RouterID& target,
RouterLookupHandler result = nullptr) override; const Key_t& whoasked,
uint64_t whoaskedTX,
const Key_t& askpeer,
RouterLookupHandler result = nullptr) override;
bool bool
LookupRouter(const RouterID& target, RouterLookupHandler result) override LookupRouter(const RouterID& target, RouterLookupHandler result) override
{ {
Key_t askpeer; Key_t askpeer;
if(!_nodes->FindClosest(Key_t(target), askpeer)) if (!_nodes->FindClosest(Key_t(target), askpeer))
{ {
return false; return false;
} }
@ -84,58 +92,72 @@ namespace llarp
/// issue dht lookup for router via askpeer and send reply to local path /// issue dht lookup for router via askpeer and send reply to local path
void void
LookupRouterForPath(const RouterID& target, uint64_t txid, LookupRouterForPath(
const PathID_t& path, const Key_t& askpeer) override; const RouterID& target,
uint64_t txid,
const PathID_t& path,
const Key_t& askpeer) override;
/// issue dht lookup for introset for addr via askpeer and send reply to /// issue dht lookup for introset for addr via askpeer and send reply to
/// local path /// local path
void void
LookupIntroSetForPath(const Key_t& addr, uint64_t txid, LookupIntroSetForPath(
const llarp::PathID_t& path, const Key_t& askpeer, const Key_t& addr,
uint64_t relayOrder) override; uint64_t txid,
const llarp::PathID_t& path,
const Key_t& askpeer,
uint64_t relayOrder) override;
/// send a dht message to peer, if keepalive is true then keep the session /// send a dht message to peer, if keepalive is true then keep the session
/// with that peer alive for 10 seconds /// with that peer alive for 10 seconds
void void
DHTSendTo(const RouterID& peer, IMessage* msg, DHTSendTo(const RouterID& peer, IMessage* msg, bool keepalive = true) override;
bool keepalive = true) override;
/// get routers closest to target excluding requester /// get routers closest to target excluding requester
bool bool
HandleExploritoryRouterLookup( HandleExploritoryRouterLookup(
const Key_t& requester, uint64_t txid, const RouterID& target, const Key_t& requester,
std::vector< std::unique_ptr< IMessage > >& reply) override; uint64_t txid,
const RouterID& target,
std::vector<std::unique_ptr<IMessage>>& reply) override;
/// handle rc lookup from requester for target /// handle rc lookup from requester for target
void void
LookupRouterRelayed( LookupRouterRelayed(
const Key_t& requester, uint64_t txid, const Key_t& target, const Key_t& requester,
uint64_t txid,
const Key_t& target,
bool recursive, bool recursive,
std::vector< std::unique_ptr< IMessage > >& replies) override; std::vector<std::unique_ptr<IMessage>>& replies) override;
/// relay a dht message from a local path to the main network /// relay a dht message from a local path to the main network
bool bool
RelayRequestForPath(const llarp::PathID_t& localPath, RelayRequestForPath(const llarp::PathID_t& localPath, const IMessage& msg) override;
const IMessage& msg) override;
/// send introset to peer as R/S /// send introset to peer as R/S
void void
PropagateLocalIntroSet(const PathID_t& from, uint64_t txid, PropagateLocalIntroSet(
const service::EncryptedIntroSet& introset, const PathID_t& from,
const Key_t& tellpeer, uint64_t relayOrder); uint64_t txid,
const service::EncryptedIntroSet& introset,
const Key_t& tellpeer,
uint64_t relayOrder);
/// send introset to peer from source with S counter and excluding peers /// send introset to peer from source with S counter and excluding peers
void void
PropagateIntroSetTo(const Key_t& from, uint64_t txid, PropagateIntroSetTo(
const service::EncryptedIntroSet& introset, const Key_t& from,
const Key_t& tellpeer, uint64_t relayOrder); uint64_t txid,
const service::EncryptedIntroSet& introset,
const Key_t& tellpeer,
uint64_t relayOrder);
/// initialize dht context and explore every exploreInterval milliseconds /// initialize dht context and explore every exploreInterval milliseconds
void void
Init(const Key_t& us, AbstractRouter* router) override; Init(const Key_t& us, AbstractRouter* router) override;
/// get localally stored introset by service address /// get localally stored introset by service address
nonstd::optional< llarp::service::EncryptedIntroSet > nonstd::optional<llarp::service::EncryptedIntroSet>
GetIntroSetByLocation(const Key_t& location) const override; GetIntroSetByLocation(const Key_t& location) const override;
void void
@ -147,12 +169,12 @@ namespace llarp
llarp::AbstractRouter* router{nullptr}; llarp::AbstractRouter* router{nullptr};
// for router contacts // for router contacts
std::unique_ptr< Bucket< RCNode > > _nodes; std::unique_ptr<Bucket<RCNode>> _nodes;
// for introduction sets // for introduction sets
std::unique_ptr< Bucket< ISNode > > _services; std::unique_ptr<Bucket<ISNode>> _services;
Bucket< ISNode >* Bucket<ISNode>*
services() override services() override
{ {
return _services.get(); return _services.get();
@ -171,7 +193,7 @@ namespace llarp
return allowTransit; return allowTransit;
} }
Bucket< RCNode >* Bucket<RCNode>*
Nodes() const override Nodes() const override
{ {
return _nodes.get(); return _nodes.get();
@ -180,14 +202,14 @@ namespace llarp
void void
PutRCNodeAsync(const RCNode& val) override PutRCNodeAsync(const RCNode& val) override
{ {
auto func = std::bind(&Bucket< RCNode >::PutNode, Nodes(), val); auto func = std::bind(&Bucket<RCNode>::PutNode, Nodes(), val);
LogicCall(router->logic(), func); LogicCall(router->logic(), func);
} }
void void
DelRCNodeAsync(const Key_t& val) override DelRCNodeAsync(const Key_t& val) override
{ {
auto func = std::bind(&Bucket< RCNode >::DelNode, Nodes(), val); auto func = std::bind(&Bucket<RCNode>::DelNode, Nodes(), val);
LogicCall(router->logic(), func); LogicCall(router->logic(), func);
} }
@ -283,16 +305,15 @@ namespace llarp
{ {
// ask N random peers for new routers // ask N random peers for new routers
llarp::LogDebug("Exploring network via ", N, " peers"); llarp::LogDebug("Exploring network via ", N, " peers");
std::set< Key_t > peers; std::set<Key_t> peers;
if(_nodes->GetManyRandom(peers, N)) if (_nodes->GetManyRandom(peers, N))
{ {
for(const auto& peer : peers) for (const auto& peer : peers)
ExploreNetworkVia(peer); ExploreNetworkVia(peer);
} }
else else
llarp::LogError("failed to select ", N, llarp::LogError("failed to select ", N, " random nodes for exploration");
" random nodes for exploration");
} }
void void
@ -313,14 +334,14 @@ namespace llarp
CleanupTX(); CleanupTX();
const llarp_time_t now = Now(); const llarp_time_t now = Now();
if(_services) if (_services)
{ {
// expire intro sets // expire intro sets
auto& nodes = _services->nodes; auto& nodes = _services->nodes;
auto itr = nodes.begin(); auto itr = nodes.begin();
while(itr != nodes.end()) while (itr != nodes.end())
{ {
if(itr->second.introset.IsExpired(now)) if (itr->second.introset.IsExpired(now))
{ {
itr = nodes.erase(itr); itr = nodes.erase(itr);
} }
@ -333,17 +354,19 @@ namespace llarp
void void
Context::LookupRouterRelayed( Context::LookupRouterRelayed(
const Key_t& requester, uint64_t txid, const Key_t& target, const Key_t& requester,
bool recursive, std::vector< std::unique_ptr< IMessage > >& replies) uint64_t txid,
const Key_t& target,
bool recursive,
std::vector<std::unique_ptr<IMessage>>& replies)
{ {
if(target == ourKey) if (target == ourKey)
{ {
// we are the target, give them our RC // we are the target, give them our RC
replies.emplace_back( replies.emplace_back(new GotRouterMessage(requester, txid, {router->rc()}, false));
new GotRouterMessage(requester, txid, {router->rc()}, false));
return; return;
} }
if(not GetRouter()->ConnectionToRouterAllowed(target.as_array())) if (not GetRouter()->ConnectionToRouterAllowed(target.as_array()))
{ {
// explicitly not allowed // explicitly not allowed
replies.emplace_back(new GotRouterMessage(requester, txid, {}, false)); replies.emplace_back(new GotRouterMessage(requester, txid, {}, false));
@ -352,10 +375,10 @@ namespace llarp
const auto rc = GetRouter()->nodedb()->FindClosestTo(target); const auto rc = GetRouter()->nodedb()->FindClosestTo(target);
const Key_t next(rc.pubkey); const Key_t next(rc.pubkey);
{ {
if(next == target) if (next == target)
{ {
// we know the target // we know the target
if(rc.ExpiresSoon(llarp::time_now_ms())) if (rc.ExpiresSoon(llarp::time_now_ms()))
{ {
// ask target for their rc to keep it updated // ask target for their rc to keep it updated
LookupRouterRecursive(target.as_array(), requester, txid, next); LookupRouterRecursive(target.as_array(), requester, txid, next);
@ -363,14 +386,13 @@ namespace llarp
else else
{ {
// send reply with rc we know of // send reply with rc we know of
replies.emplace_back( replies.emplace_back(new GotRouterMessage(requester, txid, {rc}, false));
new GotRouterMessage(requester, txid, {rc}, false));
} }
} }
else if(recursive) // are we doing a recursive lookup? else if (recursive) // are we doing a recursive lookup?
{ {
// is the next peer we ask closer to the target than us? // is the next peer we ask closer to the target than us?
if((next ^ target) < (ourKey ^ target)) if ((next ^ target) < (ourKey ^ target))
{ {
// yes it is closer, ask neighbour recursively // yes it is closer, ask neighbour recursively
LookupRouterRecursive(target.as_array(), requester, txid, next); LookupRouterRecursive(target.as_array(), requester, txid, next);
@ -379,24 +401,22 @@ namespace llarp
{ {
// no we are closer to the target so tell requester it's not there // no we are closer to the target so tell requester it's not there
// so they switch to iterative lookup // so they switch to iterative lookup
replies.emplace_back( replies.emplace_back(new GotRouterMessage(requester, txid, {}, false));
new GotRouterMessage(requester, txid, {}, false));
} }
} }
else else
{ {
// iterative lookup and we don't have it tell them who is closer // iterative lookup and we don't have it tell them who is closer
replies.emplace_back( replies.emplace_back(new GotRouterMessage(requester, next, txid, false));
new GotRouterMessage(requester, next, txid, false));
} }
} }
} }
nonstd::optional< llarp::service::EncryptedIntroSet > nonstd::optional<llarp::service::EncryptedIntroSet>
Context::GetIntroSetByLocation(const Key_t& key) const Context::GetIntroSetByLocation(const Key_t& key) const
{ {
auto itr = _services->nodes.find(key); auto itr = _services->nodes.find(key);
if(itr == _services->nodes.end()) if (itr == _services->nodes.end())
return {}; return {};
return itr->second.introset; return itr->second.introset;
} }
@ -415,23 +435,22 @@ namespace llarp
util::StatusObject util::StatusObject
Context::ExtractStatus() const Context::ExtractStatus() const
{ {
util::StatusObject obj{ util::StatusObject obj{{"pendingRouterLookups", pendingRouterLookups().ExtractStatus()},
{"pendingRouterLookups", pendingRouterLookups().ExtractStatus()}, {"pendingIntrosetLookups", _pendingIntrosetLookups.ExtractStatus()},
{"pendingIntrosetLookups", _pendingIntrosetLookups.ExtractStatus()}, {"pendingExploreLookups", pendingExploreLookups().ExtractStatus()},
{"pendingExploreLookups", pendingExploreLookups().ExtractStatus()}, {"nodes", _nodes->ExtractStatus()},
{"nodes", _nodes->ExtractStatus()}, {"services", _services->ExtractStatus()},
{"services", _services->ExtractStatus()}, {"ourKey", ourKey.ToHex()}};
{"ourKey", ourKey.ToHex()}};
return obj; return obj;
} }
void void
Context::Init(const Key_t& us, AbstractRouter* r) Context::Init(const Key_t& us, AbstractRouter* r)
{ {
router = r; router = r;
ourKey = us; ourKey = us;
_nodes = std::make_unique< Bucket< RCNode > >(ourKey, llarp::randint); _nodes = std::make_unique<Bucket<RCNode>>(ourKey, llarp::randint);
_services = std::make_unique< Bucket< ISNode > >(ourKey, llarp::randint); _services = std::make_unique<Bucket<ISNode>>(ourKey, llarp::randint);
llarp::LogDebug("initialize dht with key ", ourKey); llarp::LogDebug("initialize dht with key ", ourKey);
// start cleanup timer // start cleanup timer
ScheduleCleanupTimer(); ScheduleCleanupTimer();
@ -441,8 +460,7 @@ namespace llarp
Context::ScheduleCleanupTimer() Context::ScheduleCleanupTimer()
{ {
router->logic()->call_later( router->logic()->call_later(
1s, 1s, std::bind(&llarp::dht::Context::handle_cleaner_timer, this, 1000));
std::bind(&llarp::dht::Context::handle_cleaner_timer, this, 1000));
} }
void void
@ -451,7 +469,7 @@ namespace llarp
llarp::DHTImmediateMessage m; llarp::DHTImmediateMessage m;
m.msgs.emplace_back(msg); m.msgs.emplace_back(msg);
router->SendToOrQueue(peer, &m, [](SendStatus status) { router->SendToOrQueue(peer, &m, [](SendStatus status) {
if(status != SendStatus::Success) if (status != SendStatus::Success)
LogInfo("DHTSendTo unsuccessful, status: ", (int)status); LogInfo("DHTSendTo unsuccessful, status: ", (int)status);
}); });
auto now = Now(); auto now = Now();
@ -466,9 +484,9 @@ namespace llarp
Context::RelayRequestForPath(const llarp::PathID_t& id, const IMessage& msg) Context::RelayRequestForPath(const llarp::PathID_t& id, const IMessage& msg)
{ {
llarp::routing::DHTMessage reply; llarp::routing::DHTMessage reply;
if(!msg.HandleMessage(router->dht(), reply.M)) if (!msg.HandleMessage(router->dht(), reply.M))
return false; return false;
if(not reply.M.empty()) if (not reply.M.empty())
{ {
auto path = router->pathContext().GetByUpstream(router->pubkey(), id); auto path = router->pathContext().GetByUpstream(router->pubkey(), id);
return path && path->SendRoutingMessage(reply, router); return path && path->SendRoutingMessage(reply, router);
@ -477,106 +495,120 @@ namespace llarp
} }
void void
Context::LookupIntroSetForPath(const Key_t& addr, uint64_t txid, Context::LookupIntroSetForPath(
const llarp::PathID_t& path, const Key_t& addr,
const Key_t& askpeer, uint64_t relayOrder) uint64_t txid,
const llarp::PathID_t& path,
const Key_t& askpeer,
uint64_t relayOrder)
{ {
const TXOwner asker(OurKey(), txid); const TXOwner asker(OurKey(), txid);
const TXOwner peer(askpeer, ++ids); const TXOwner peer(askpeer, ++ids);
_pendingIntrosetLookups.NewTX( _pendingIntrosetLookups.NewTX(
peer, asker, asker, peer,
new LocalServiceAddressLookup(path, txid, relayOrder, addr, this, asker,
askpeer)); asker,
new LocalServiceAddressLookup(path, txid, relayOrder, addr, this, askpeer));
} }
void void
Context::PropagateIntroSetTo(const Key_t& from, uint64_t txid, Context::PropagateIntroSetTo(
const service::EncryptedIntroSet& introset, const Key_t& from,
const Key_t& tellpeer, uint64_t relayOrder) uint64_t txid,
const service::EncryptedIntroSet& introset,
const Key_t& tellpeer,
uint64_t relayOrder)
{ {
const TXOwner asker(from, txid); const TXOwner asker(from, txid);
const TXOwner peer(tellpeer, ++ids); const TXOwner peer(tellpeer, ++ids);
_pendingIntrosetLookups.NewTX( _pendingIntrosetLookups.NewTX(
peer, asker, asker, peer, asker, asker, new PublishServiceJob(asker, introset, this, relayOrder));
new PublishServiceJob(asker, introset, this, relayOrder));
} }
void void
Context::PropagateLocalIntroSet(const PathID_t& from, uint64_t txid, Context::PropagateLocalIntroSet(
const service::EncryptedIntroSet& introset, const PathID_t& from,
const Key_t& tellpeer, uint64_t relayOrder) uint64_t txid,
const service::EncryptedIntroSet& introset,
const Key_t& tellpeer,
uint64_t relayOrder)
{ {
const TXOwner asker(OurKey(), txid); const TXOwner asker(OurKey(), txid);
const TXOwner peer(tellpeer, ++ids); const TXOwner peer(tellpeer, ++ids);
_pendingIntrosetLookups.NewTX( _pendingIntrosetLookups.NewTX(
peer, asker, peer, peer,
new LocalPublishServiceJob(peer, from, txid, introset, this, asker,
relayOrder)); peer,
new LocalPublishServiceJob(peer, from, txid, introset, this, relayOrder));
} }
void void
Context::LookupIntroSetRelayed( Context::LookupIntroSetRelayed(
const Key_t& addr, const Key_t& whoasked, uint64_t txid, const Key_t& addr,
const Key_t& askpeer, uint64_t relayOrder, const Key_t& whoasked,
uint64_t txid,
const Key_t& askpeer,
uint64_t relayOrder,
service::EncryptedIntroSetLookupHandler handler) service::EncryptedIntroSetLookupHandler handler)
{ {
const TXOwner asker(whoasked, txid); const TXOwner asker(whoasked, txid);
const TXOwner peer(askpeer, ++ids); const TXOwner peer(askpeer, ++ids);
_pendingIntrosetLookups.NewTX( _pendingIntrosetLookups.NewTX(
peer, asker, asker, peer, asker, asker, new ServiceAddressLookup(asker, addr, this, relayOrder, handler));
new ServiceAddressLookup(asker, addr, this, relayOrder, handler));
} }
void void
Context::LookupIntroSetDirect( Context::LookupIntroSetDirect(
const Key_t& addr, const Key_t& whoasked, uint64_t txid, const Key_t& addr,
const Key_t& askpeer, service::EncryptedIntroSetLookupHandler handler) const Key_t& whoasked,
uint64_t txid,
const Key_t& askpeer,
service::EncryptedIntroSetLookupHandler handler)
{ {
const TXOwner asker(whoasked, txid); const TXOwner asker(whoasked, txid);
const TXOwner peer(askpeer, ++ids); const TXOwner peer(askpeer, ++ids);
_pendingIntrosetLookups.NewTX( _pendingIntrosetLookups.NewTX(
peer, asker, asker, peer, asker, asker, new ServiceAddressLookup(asker, addr, this, 0, handler), 1s);
new ServiceAddressLookup(asker, addr, this, 0, handler), 1s);
} }
bool bool
Context::HandleExploritoryRouterLookup( Context::HandleExploritoryRouterLookup(
const Key_t& requester, uint64_t txid, const RouterID& target, const Key_t& requester,
std::vector< std::unique_ptr< IMessage > >& reply) uint64_t txid,
const RouterID& target,
std::vector<std::unique_ptr<IMessage>>& reply)
{ {
std::vector< RouterID > closer; std::vector<RouterID> closer;
const Key_t t(target.as_array()); const Key_t t(target.as_array());
std::set< Key_t > foundRouters; std::set<Key_t> foundRouters;
if(!_nodes) if (!_nodes)
return false; return false;
const size_t nodeCount = _nodes->size(); const size_t nodeCount = _nodes->size();
if(nodeCount == 0) if (nodeCount == 0)
{ {
llarp::LogError( llarp::LogError("cannot handle exploritory router lookup, no dht peers");
"cannot handle exploritory router lookup, no dht peers");
return false; return false;
} }
llarp::LogDebug("We have ", _nodes->size(), llarp::LogDebug("We have ", _nodes->size(), " connected nodes into the DHT");
" connected nodes into the DHT");
// ourKey should never be in the connected list // ourKey should never be in the connected list
// requester is likely in the connected list // requester is likely in the connected list
// 4 or connection nodes (minus a potential requestor), whatever is less // 4 or connection nodes (minus a potential requestor), whatever is less
if(!_nodes->GetManyNearExcluding(t, foundRouters, if (!_nodes->GetManyNearExcluding(
std::min(nodeCount, size_t{4}), t, foundRouters, std::min(nodeCount, size_t{4}), std::set<Key_t>{ourKey, requester}))
std::set< Key_t >{ourKey, requester}))
{ {
llarp::LogError( llarp::LogError(
"not enough dht nodes to handle exploritory router lookup, " "not enough dht nodes to handle exploritory router lookup, "
"have ", "have ",
nodeCount, " dht peers"); nodeCount,
" dht peers");
return false; return false;
} }
for(const auto& f : foundRouters) for (const auto& f : foundRouters)
{ {
const RouterID id = f.as_array(); const RouterID id = f.as_array();
// discard shit routers // discard shit routers
if(router->routerProfiling().IsBadForConnect(id)) if (router->routerProfiling().IsBadForConnect(id))
continue; continue;
closer.emplace_back(id); closer.emplace_back(id);
} }
@ -586,29 +618,28 @@ namespace llarp
} }
void void
Context::LookupRouterForPath(const RouterID& target, uint64_t txid, Context::LookupRouterForPath(
const llarp::PathID_t& path, const RouterID& target, uint64_t txid, const llarp::PathID_t& path, const Key_t& askpeer)
const Key_t& askpeer)
{ {
const TXOwner peer(askpeer, ++ids); const TXOwner peer(askpeer, ++ids);
const TXOwner whoasked(OurKey(), txid); const TXOwner whoasked(OurKey(), txid);
_pendingRouterLookups.NewTX( _pendingRouterLookups.NewTX(
peer, whoasked, target, peer, whoasked, target, new LocalRouterLookup(path, txid, target, this));
new LocalRouterLookup(path, txid, target, this));
} }
void void
Context::LookupRouterRecursive(const RouterID& target, Context::LookupRouterRecursive(
const Key_t& whoasked, uint64_t txid, const RouterID& target,
const Key_t& askpeer, const Key_t& whoasked,
RouterLookupHandler handler) uint64_t txid,
const Key_t& askpeer,
RouterLookupHandler handler)
{ {
const TXOwner asker(whoasked, txid); const TXOwner asker(whoasked, txid);
const TXOwner peer(askpeer, ++ids); const TXOwner peer(askpeer, ++ids);
_pendingRouterLookups.NewTX( _pendingRouterLookups.NewTX(
peer, asker, target, peer, asker, target, new RecursiveRouterLookup(asker, target, this, handler));
new RecursiveRouterLookup(asker, target, this, handler));
} }
llarp_time_t llarp_time_t
@ -617,10 +648,10 @@ namespace llarp
return router->Now(); return router->Now();
} }
std::unique_ptr< AbstractContext > std::unique_ptr<AbstractContext>
makeContext() makeContext()
{ {
return std::make_unique< Context >(); return std::make_unique<Context>();
} }
} // namespace dht } // namespace dht

@ -34,12 +34,9 @@ namespace llarp
struct AbstractContext struct AbstractContext
{ {
using PendingIntrosetLookups = using PendingIntrosetLookups = TXHolder<TXOwner, service::EncryptedIntroSet, TXOwner::Hash>;
TXHolder< TXOwner, service::EncryptedIntroSet, TXOwner::Hash >; using PendingRouterLookups = TXHolder<RouterID, RouterContact, RouterID::Hash>;
using PendingRouterLookups = using PendingExploreLookups = TXHolder<RouterID, RouterID, RouterID::Hash>;
TXHolder< RouterID, RouterContact, RouterID::Hash >;
using PendingExploreLookups =
TXHolder< RouterID, RouterID, RouterID::Hash >;
virtual ~AbstractContext() = 0; virtual ~AbstractContext() = 0;
@ -47,37 +44,49 @@ namespace llarp
LookupRouter(const RouterID& target, RouterLookupHandler result) = 0; LookupRouter(const RouterID& target, RouterLookupHandler result) = 0;
virtual void virtual void
LookupRouterRecursive(const RouterID& target, const Key_t& whoasked, LookupRouterRecursive(
uint64_t whoaskedTX, const Key_t& askpeer, const RouterID& target,
RouterLookupHandler result = nullptr) = 0; const Key_t& whoasked,
uint64_t whoaskedTX,
const Key_t& askpeer,
RouterLookupHandler result = nullptr) = 0;
/// Ask a Service Node to perform an Introset lookup for us /// Ask a Service Node to perform an Introset lookup for us
virtual void virtual void
LookupIntroSetRelayed(const Key_t& target, const Key_t& whoasked, LookupIntroSetRelayed(
uint64_t whoaskedTX, const Key_t& askpeer, const Key_t& target,
uint64_t relayOrder, const Key_t& whoasked,
service::EncryptedIntroSetLookupHandler result = uint64_t whoaskedTX,
service::EncryptedIntroSetLookupHandler()) = 0; const Key_t& askpeer,
uint64_t relayOrder,
service::EncryptedIntroSetLookupHandler result =
service::EncryptedIntroSetLookupHandler()) = 0;
/// Directly as a Service Node for an Introset /// Directly as a Service Node for an Introset
virtual void virtual void
LookupIntroSetDirect(const Key_t& target, const Key_t& whoasked, LookupIntroSetDirect(
uint64_t whoaskedTX, const Key_t& askpeer, const Key_t& target,
service::EncryptedIntroSetLookupHandler result = const Key_t& whoasked,
service::EncryptedIntroSetLookupHandler()) = 0; uint64_t whoaskedTX,
const Key_t& askpeer,
service::EncryptedIntroSetLookupHandler result =
service::EncryptedIntroSetLookupHandler()) = 0;
virtual bool virtual bool
HasRouterLookup(const RouterID& target) const = 0; HasRouterLookup(const RouterID& target) const = 0;
/// issue dht lookup for router via askpeer and send reply to local path /// issue dht lookup for router via askpeer and send reply to local path
virtual void virtual void
LookupRouterForPath(const RouterID& target, uint64_t txid, LookupRouterForPath(
const PathID_t& path, const Key_t& askpeer) = 0; const RouterID& target, uint64_t txid, const PathID_t& path, const Key_t& askpeer) = 0;
virtual void virtual void
LookupIntroSetForPath(const Key_t& addr, uint64_t txid, LookupIntroSetForPath(
const PathID_t& path, const Key_t& askpeer, const Key_t& addr,
uint64_t relayOrder) = 0; uint64_t txid,
const PathID_t& path,
const Key_t& askpeer,
uint64_t relayOrder) = 0;
virtual void virtual void
DHTSendTo(const RouterID& peer, IMessage* msg, bool keepalive = true) = 0; DHTSendTo(const RouterID& peer, IMessage* msg, bool keepalive = true) = 0;
@ -85,35 +94,45 @@ namespace llarp
/// get routers closest to target excluding requester /// get routers closest to target excluding requester
virtual bool virtual bool
HandleExploritoryRouterLookup( HandleExploritoryRouterLookup(
const Key_t& requester, uint64_t txid, const RouterID& target, const Key_t& requester,
std::vector< std::unique_ptr< IMessage > >& reply) = 0; uint64_t txid,
const RouterID& target,
std::vector<std::unique_ptr<IMessage>>& reply) = 0;
/// handle rc lookup from requester for target /// handle rc lookup from requester for target
virtual void virtual void
LookupRouterRelayed( LookupRouterRelayed(
const Key_t& requester, uint64_t txid, const Key_t& target, const Key_t& requester,
uint64_t txid,
const Key_t& target,
bool recursive, bool recursive,
std::vector< std::unique_ptr< IMessage > >& replies) = 0; std::vector<std::unique_ptr<IMessage>>& replies) = 0;
virtual bool virtual bool
RelayRequestForPath(const PathID_t& localPath, const IMessage& msg) = 0; RelayRequestForPath(const PathID_t& localPath, const IMessage& msg) = 0;
/// send introset to peer from source with S counter and excluding peers /// send introset to peer from source with S counter and excluding peers
virtual void virtual void
PropagateLocalIntroSet(const PathID_t& path, uint64_t sourceTX, PropagateLocalIntroSet(
const service::EncryptedIntroSet& introset, const PathID_t& path,
const Key_t& peer, uint64_t relayOrder) = 0; uint64_t sourceTX,
const service::EncryptedIntroSet& introset,
const Key_t& peer,
uint64_t relayOrder) = 0;
/// send introset to peer from source with S counter and excluding peers /// send introset to peer from source with S counter and excluding peers
virtual void virtual void
PropagateIntroSetTo(const Key_t& source, uint64_t sourceTX, PropagateIntroSetTo(
const service::EncryptedIntroSet& introset, const Key_t& source,
const Key_t& peer, uint64_t relayOrder) = 0; uint64_t sourceTX,
const service::EncryptedIntroSet& introset,
const Key_t& peer,
uint64_t relayOrder) = 0;
virtual void virtual void
Init(const Key_t& us, AbstractRouter* router) = 0; Init(const Key_t& us, AbstractRouter* router) = 0;
virtual nonstd::optional< llarp::service::EncryptedIntroSet > virtual nonstd::optional<llarp::service::EncryptedIntroSet>
GetIntroSetByLocation(const Key_t& location) const = 0; GetIntroSetByLocation(const Key_t& location) const = 0;
virtual llarp_time_t virtual llarp_time_t
@ -149,7 +168,7 @@ namespace llarp
virtual const PendingExploreLookups& virtual const PendingExploreLookups&
pendingExploreLookups() const = 0; pendingExploreLookups() const = 0;
virtual Bucket< ISNode >* virtual Bucket<ISNode>*
services() = 0; services() = 0;
virtual bool& virtual bool&
@ -157,7 +176,7 @@ namespace llarp
virtual const bool& virtual const bool&
AllowTransit() const = 0; AllowTransit() const = 0;
virtual Bucket< RCNode >* virtual Bucket<RCNode>*
Nodes() const = 0; Nodes() const = 0;
virtual void virtual void
@ -173,14 +192,14 @@ namespace llarp
StoreRC(const RouterContact rc) const = 0; StoreRC(const RouterContact rc) const = 0;
}; };
std::unique_ptr< AbstractContext > std::unique_ptr<AbstractContext>
makeContext(); makeContext();
} // namespace dht } // namespace dht
} // namespace llarp } // namespace llarp
struct llarp_dht_context struct llarp_dht_context
{ {
std::unique_ptr< llarp::dht::AbstractContext > impl; std::unique_ptr<llarp::dht::AbstractContext> impl;
llarp::AbstractRouter* parent; llarp::AbstractRouter* parent;
llarp_dht_context(llarp::AbstractRouter* router); llarp_dht_context(llarp::AbstractRouter* router);
}; };

@ -2,47 +2,46 @@
#include <dht/dht.h> #include <dht/dht.h>
#include <router_contact.hpp> #include <router_contact.hpp>
llarp_dht_context::llarp_dht_context(llarp::AbstractRouter *router) llarp_dht_context::llarp_dht_context(llarp::AbstractRouter* router)
{ {
parent = router; parent = router;
impl = llarp::dht::makeContext(); impl = llarp::dht::makeContext();
} }
struct llarp_dht_context * struct llarp_dht_context*
llarp_dht_context_new(llarp::AbstractRouter *router) llarp_dht_context_new(llarp::AbstractRouter* router)
{ {
return new llarp_dht_context(router); return new llarp_dht_context(router);
} }
void void
llarp_dht_context_free(struct llarp_dht_context *ctx) llarp_dht_context_free(struct llarp_dht_context* ctx)
{ {
delete ctx; delete ctx;
} }
void void
__llarp_dht_remove_peer(struct llarp_dht_context *ctx, const byte_t *id) __llarp_dht_remove_peer(struct llarp_dht_context* ctx, const byte_t* id)
{ {
ctx->impl->Nodes()->DelNode(llarp::dht::Key_t(id)); ctx->impl->Nodes()->DelNode(llarp::dht::Key_t(id));
} }
void void
llarp_dht_allow_transit(llarp_dht_context *ctx) llarp_dht_allow_transit(llarp_dht_context* ctx)
{ {
ctx->impl->AllowTransit() = true; ctx->impl->AllowTransit() = true;
} }
void void
llarp_dht_context_start(struct llarp_dht_context *ctx, const byte_t *key) llarp_dht_context_start(struct llarp_dht_context* ctx, const byte_t* key)
{ {
ctx->impl->Init(llarp::dht::Key_t(key), ctx->parent); ctx->impl->Init(llarp::dht::Key_t(key), ctx->parent);
} }
void void
llarp_dht_lookup_router(struct llarp_dht_context *ctx, llarp_dht_lookup_router(struct llarp_dht_context* ctx, struct llarp_router_lookup_job* job)
struct llarp_router_lookup_job *job)
{ {
job->dht = ctx; job->dht = ctx;
job->found = false; job->found = false;
job->result.Clear(); job->result.Clear();
// llarp_rc_clear(&job->result); // llarp_rc_clear(&job->result);

@ -59,7 +59,6 @@ void
__llarp_dht_remove_peer(struct llarp_dht_context* ctx, const byte_t* id); __llarp_dht_remove_peer(struct llarp_dht_context* ctx, const byte_t* id);
void void
llarp_dht_lookup_router(struct llarp_dht_context* ctx, llarp_dht_lookup_router(struct llarp_dht_context* ctx, struct llarp_router_lookup_job* job);
struct llarp_router_lookup_job* job);
#endif #endif

@ -13,14 +13,11 @@ namespace llarp
namespace dht namespace dht
{ {
void void
ExploreNetworkJob::Start(const TXOwner &peer) ExploreNetworkJob::Start(const TXOwner& peer)
{ {
auto msg = new FindRouterMessage(peer.txid); auto msg = new FindRouterMessage(peer.txid);
auto router = parent->GetRouter(); auto router = parent->GetRouter();
router->NotifyRouterEvent< tooling::FindRouterSentEvent >( router->NotifyRouterEvent<tooling::FindRouterSentEvent>(router->pubkey(), msg);
router->pubkey(),
msg);
parent->DHTSendTo(peer.node.as_array(), msg); parent->DHTSendTo(peer.node.as_array(), msg);
} }
@ -32,15 +29,13 @@ namespace llarp
auto router = parent->GetRouter(); auto router = parent->GetRouter();
using std::placeholders::_1; using std::placeholders::_1;
for(const auto &pk : valuesFound) for (const auto& pk : valuesFound)
{ {
// lookup router // lookup router
if(router and router->nodedb()->Has(pk)) if (router and router->nodedb()->Has(pk))
continue; continue;
parent->LookupRouter( parent->LookupRouter(
pk, pk, std::bind(&AbstractRouter::HandleDHTLookupForExplore, router, pk, _1));
std::bind(&AbstractRouter::HandleDHTLookupForExplore, router, pk,
_1));
} }
} }
} // namespace dht } // namespace dht

@ -8,22 +8,22 @@ namespace llarp
{ {
namespace dht namespace dht
{ {
struct ExploreNetworkJob : public TX< RouterID, RouterID > struct ExploreNetworkJob : public TX<RouterID, RouterID>
{ {
ExploreNetworkJob(const RouterID &peer, AbstractContext *ctx) ExploreNetworkJob(const RouterID& peer, AbstractContext* ctx)
: TX< RouterID, RouterID >(TXOwner{}, peer, ctx) : TX<RouterID, RouterID>(TXOwner{}, peer, ctx)
{ {
} }
bool bool
Validate(const RouterID &) const override Validate(const RouterID&) const override
{ {
// TODO: check with lokid // TODO: check with lokid
return true; return true;
} }
void void
Start(const TXOwner &peer) override; Start(const TXOwner& peer) override;
void void
SendReply() override; SendReply() override;

@ -10,22 +10,21 @@ namespace llarp
{ {
namespace dht namespace dht
{ {
struct Key_t : public AlignedBuffer< 32 > struct Key_t : public AlignedBuffer<32>
{ {
explicit Key_t(const byte_t* buf) : AlignedBuffer< SIZE >(buf) explicit Key_t(const byte_t* buf) : AlignedBuffer<SIZE>(buf)
{ {
} }
explicit Key_t(const Data& data) : AlignedBuffer< SIZE >(data) explicit Key_t(const Data& data) : AlignedBuffer<SIZE>(data)
{ {
} }
explicit Key_t(const AlignedBuffer< SIZE >& data) explicit Key_t(const AlignedBuffer<SIZE>& data) : AlignedBuffer<SIZE>(data)
: AlignedBuffer< SIZE >(data)
{ {
} }
Key_t() : AlignedBuffer< SIZE >() Key_t() : AlignedBuffer<SIZE>()
{ {
} }
@ -50,8 +49,7 @@ namespace llarp
operator^(const Key_t& other) const operator^(const Key_t& other) const
{ {
Key_t dist; Key_t dist;
std::transform(begin(), end(), other.begin(), dist.begin(), std::transform(begin(), end(), other.begin(), dist.begin(), std::bit_xor<byte_t>());
std::bit_xor< byte_t >());
return dist; return dist;
} }

@ -12,11 +12,9 @@ namespace llarp
{ {
namespace dht namespace dht
{ {
LocalRouterLookup::LocalRouterLookup(const PathID_t &path, uint64_t txid, LocalRouterLookup::LocalRouterLookup(
const RouterID &_target, const PathID_t& path, uint64_t txid, const RouterID& _target, AbstractContext* ctx)
AbstractContext *ctx) : RecursiveRouterLookup(TXOwner{ctx->OurKey(), txid}, _target, ctx, nullptr)
: RecursiveRouterLookup(TXOwner{ctx->OurKey(), txid}, _target, ctx,
nullptr)
, localPath(path) , localPath(path)
{ {
} }
@ -24,9 +22,9 @@ namespace llarp
void void
LocalRouterLookup::SendReply() LocalRouterLookup::SendReply()
{ {
auto path = parent->GetRouter()->pathContext().GetByUpstream( auto path =
parent->OurKey().as_array(), localPath); parent->GetRouter()->pathContext().GetByUpstream(parent->OurKey().as_array(), localPath);
if(!path) if (!path)
{ {
llarp::LogWarn( llarp::LogWarn(
"did not send reply for relayed dht request, no such local path " "did not send reply for relayed dht request, no such local path "
@ -34,16 +32,16 @@ namespace llarp
localPath); localPath);
return; return;
} }
if(valuesFound.size()) if (valuesFound.size())
{ {
RouterContact found; RouterContact found;
for(const auto &rc : valuesFound) for (const auto& rc : valuesFound)
{ {
if(rc.OtherIsNewer(found)) if (rc.OtherIsNewer(found))
found = rc; found = rc;
} }
valuesFound.clear(); valuesFound.clear();
if(not found.pubkey.IsZero()) if (not found.pubkey.IsZero())
{ {
valuesFound.resize(1); valuesFound.resize(1);
valuesFound[0] = found; valuesFound[0] = found;
@ -54,9 +52,8 @@ namespace llarp
} }
} }
routing::DHTMessage msg; routing::DHTMessage msg;
msg.M.emplace_back(new GotRouterMessage(parent->OurKey(), whoasked.txid, msg.M.emplace_back(new GotRouterMessage(parent->OurKey(), whoasked.txid, valuesFound, true));
valuesFound, true)); if (!path->SendRoutingMessage(msg, parent->GetRouter()))
if(!path->SendRoutingMessage(msg, parent->GetRouter()))
{ {
llarp::LogWarn( llarp::LogWarn(
"failed to send routing message when informing result of dht " "failed to send routing message when informing result of dht "

@ -15,8 +15,8 @@ namespace llarp
{ {
PathID_t localPath; PathID_t localPath;
LocalRouterLookup(const PathID_t &path, uint64_t txid, LocalRouterLookup(
const RouterID &target, AbstractContext *ctx); const PathID_t& path, uint64_t txid, const RouterID& target, AbstractContext* ctx);
void void
SendReply() override; SendReply() override;

@ -12,11 +12,13 @@ namespace llarp
namespace dht namespace dht
{ {
LocalServiceAddressLookup::LocalServiceAddressLookup( LocalServiceAddressLookup::LocalServiceAddressLookup(
const PathID_t &pathid, uint64_t txid, uint64_t relayOrder, const PathID_t& pathid,
const Key_t &addr, AbstractContext *ctx, uint64_t txid,
__attribute__((unused)) const Key_t &askpeer) uint64_t relayOrder,
: ServiceAddressLookup(TXOwner{ctx->OurKey(), txid}, addr, ctx, const Key_t& addr,
relayOrder, nullptr) AbstractContext* ctx,
__attribute__((unused)) const Key_t& askpeer)
: ServiceAddressLookup(TXOwner{ctx->OurKey(), txid}, addr, ctx, relayOrder, nullptr)
, localPath(pathid) , localPath(pathid)
{ {
} }
@ -24,9 +26,9 @@ namespace llarp
void void
LocalServiceAddressLookup::SendReply() LocalServiceAddressLookup::SendReply()
{ {
auto path = parent->GetRouter()->pathContext().GetByUpstream( auto path =
parent->OurKey().as_array(), localPath); parent->GetRouter()->pathContext().GetByUpstream(parent->OurKey().as_array(), localPath);
if(!path) if (!path)
{ {
llarp::LogWarn( llarp::LogWarn(
"did not send reply for relayed dht request, no such local path " "did not send reply for relayed dht request, no such local path "
@ -35,12 +37,12 @@ namespace llarp
return; return;
} }
// pick newest if we have more than 1 result // pick newest if we have more than 1 result
if(valuesFound.size()) if (valuesFound.size())
{ {
service::EncryptedIntroSet found; service::EncryptedIntroSet found;
for(const auto &introset : valuesFound) for (const auto& introset : valuesFound)
{ {
if(found.OtherIsNewer(introset)) if (found.OtherIsNewer(introset))
found = introset; found = introset;
} }
valuesFound.clear(); valuesFound.clear();
@ -48,7 +50,7 @@ namespace llarp
} }
routing::DHTMessage msg; routing::DHTMessage msg;
msg.M.emplace_back(new GotIntroMessage(valuesFound, whoasked.txid)); msg.M.emplace_back(new GotIntroMessage(valuesFound, whoasked.txid));
if(!path->SendRoutingMessage(msg, parent->GetRouter())) if (!path->SendRoutingMessage(msg, parent->GetRouter()))
{ {
llarp::LogWarn( llarp::LogWarn(
"failed to send routing message when informing result of dht " "failed to send routing message when informing result of dht "

@ -13,10 +13,13 @@ namespace llarp
{ {
PathID_t localPath; PathID_t localPath;
LocalServiceAddressLookup(const PathID_t &pathid, uint64_t txid, LocalServiceAddressLookup(
uint64_t relayOrder, const Key_t &addr, const PathID_t& pathid,
AbstractContext *ctx, uint64_t txid,
__attribute__((unused)) const Key_t &askpeer); uint64_t relayOrder,
const Key_t& addr,
AbstractContext* ctx,
__attribute__((unused)) const Key_t& askpeer);
void void
SendReply() override; SendReply() override;

@ -10,20 +10,18 @@ namespace llarp
{ {
namespace dht namespace dht
{ {
LocalTagLookup::LocalTagLookup(const PathID_t &path, uint64_t txid, LocalTagLookup::LocalTagLookup(
const service::Tag &_target, const PathID_t& path, uint64_t txid, const service::Tag& _target, AbstractContext* ctx)
AbstractContext *ctx) : TagLookup(TXOwner{ctx->OurKey(), txid}, _target, ctx, 0), localPath(path)
: TagLookup(TXOwner{ctx->OurKey(), txid}, _target, ctx, 0)
, localPath(path)
{ {
} }
void void
LocalTagLookup::SendReply() LocalTagLookup::SendReply()
{ {
auto path = parent->GetRouter()->pathContext().GetByUpstream( auto path =
parent->OurKey().as_array(), localPath); parent->GetRouter()->pathContext().GetByUpstream(parent->OurKey().as_array(), localPath);
if(!path) if (!path)
{ {
llarp::LogWarn( llarp::LogWarn(
"did not send reply for relayed dht request, no such local path " "did not send reply for relayed dht request, no such local path "
@ -33,7 +31,7 @@ namespace llarp
} }
routing::DHTMessage msg; routing::DHTMessage msg;
msg.M.emplace_back(new GotIntroMessage(valuesFound, whoasked.txid)); msg.M.emplace_back(new GotIntroMessage(valuesFound, whoasked.txid));
if(!path->SendRoutingMessage(msg, parent->GetRouter())) if (!path->SendRoutingMessage(msg, parent->GetRouter()))
{ {
llarp::LogWarn( llarp::LogWarn(
"failed to send routing message when informing result of dht " "failed to send routing message when informing result of dht "

@ -11,8 +11,8 @@ namespace llarp
{ {
PathID_t localPath; PathID_t localPath;
LocalTagLookup(const PathID_t &path, uint64_t txid, LocalTagLookup(
const service::Tag &target, AbstractContext *ctx); const PathID_t& path, uint64_t txid, const service::Tag& target, AbstractContext* ctx);
void void
SendReply() override; SendReply() override;

@ -14,62 +14,60 @@ namespace llarp
{ {
struct MessageDecoder struct MessageDecoder
{ {
const Key_t &From; const Key_t& From;
IMessage::Ptr_t msg; IMessage::Ptr_t msg;
bool firstKey = true; bool firstKey = true;
bool relayed = false; bool relayed = false;
MessageDecoder(const Key_t &from, bool wasRelayed) MessageDecoder(const Key_t& from, bool wasRelayed) : From(from), relayed(wasRelayed)
: From(from), relayed(wasRelayed)
{ {
} }
bool bool
operator()(llarp_buffer_t *buffer, llarp_buffer_t *key) operator()(llarp_buffer_t* buffer, llarp_buffer_t* key)
{ {
llarp_buffer_t strbuf; llarp_buffer_t strbuf;
// check for empty dict // check for empty dict
if(!key) if (!key)
return !firstKey; return !firstKey;
// first key // first key
if(firstKey) if (firstKey)
{ {
if(!(*key == "A")) if (!(*key == "A"))
return false; return false;
if(!bencode_read_string(buffer, &strbuf)) if (!bencode_read_string(buffer, &strbuf))
return false; return false;
// bad msg size? // bad msg size?
if(strbuf.sz != 1) if (strbuf.sz != 1)
return false; return false;
llarp::LogDebug("Handle DHT message ", *strbuf.base, llarp::LogDebug("Handle DHT message ", *strbuf.base, " relayed=", relayed);
" relayed=", relayed); switch (*strbuf.base)
switch(*strbuf.base)
{ {
case 'F': case 'F':
msg = std::make_unique< FindIntroMessage >(From, relayed, 0); msg = std::make_unique<FindIntroMessage>(From, relayed, 0);
break; break;
case 'R': case 'R':
if(relayed) if (relayed)
msg = std::make_unique< RelayedFindRouterMessage >(From); msg = std::make_unique<RelayedFindRouterMessage>(From);
else else
msg = std::make_unique< FindRouterMessage >(From); msg = std::make_unique<FindRouterMessage>(From);
break; break;
case 'S': case 'S':
msg = std::make_unique< GotRouterMessage >(From, relayed); msg = std::make_unique<GotRouterMessage>(From, relayed);
break; break;
case 'I': case 'I':
msg = std::make_unique< PublishIntroMessage >(From, relayed); msg = std::make_unique<PublishIntroMessage>(From, relayed);
break; break;
case 'G': case 'G':
if(relayed) if (relayed)
{ {
msg = std::make_unique< RelayedGotIntroMessage >(); msg = std::make_unique<RelayedGotIntroMessage>();
break; break;
} }
else else
{ {
msg = std::make_unique< GotIntroMessage >(From); msg = std::make_unique<GotIntroMessage>(From);
break; break;
} }
default: default:
@ -86,10 +84,10 @@ namespace llarp
}; };
IMessage::Ptr_t IMessage::Ptr_t
DecodeMesssage(const Key_t &from, llarp_buffer_t *buf, bool relayed) DecodeMesssage(const Key_t& from, llarp_buffer_t* buf, bool relayed)
{ {
MessageDecoder dec(from, relayed); MessageDecoder dec(from, relayed);
if(!bencode_read_dict(dec, buf)) if (!bencode_read_dict(dec, buf))
return nullptr; return nullptr;
return std::move(dec.msg); return std::move(dec.msg);
@ -97,23 +95,22 @@ namespace llarp
struct ListDecoder struct ListDecoder
{ {
ListDecoder(bool hasRelayed, const Key_t &from, ListDecoder(bool hasRelayed, const Key_t& from, std::vector<IMessage::Ptr_t>& list)
std::vector< IMessage::Ptr_t > &list)
: relayed(hasRelayed), From(from), l(list) : relayed(hasRelayed), From(from), l(list)
{ {
} }
bool relayed; bool relayed;
const Key_t &From; const Key_t& From;
std::vector< IMessage::Ptr_t > &l; std::vector<IMessage::Ptr_t>& l;
bool bool
operator()(llarp_buffer_t *buffer, bool has) operator()(llarp_buffer_t* buffer, bool has)
{ {
if(!has) if (!has)
return true; return true;
auto msg = DecodeMesssage(From, buffer, relayed); auto msg = DecodeMesssage(From, buffer, relayed);
if(msg) if (msg)
{ {
l.emplace_back(std::move(msg)); l.emplace_back(std::move(msg));
return true; return true;
@ -124,8 +121,8 @@ namespace llarp
}; };
bool bool
DecodeMesssageList(Key_t from, llarp_buffer_t *buf, DecodeMesssageList(
std::vector< IMessage::Ptr_t > &list, bool relayed) Key_t from, llarp_buffer_t* buf, std::vector<IMessage::Ptr_t>& list, bool relayed)
{ {
ListDecoder dec(relayed, from, list); ListDecoder dec(relayed, from, list);
return bencode_read_list(dec, buf); return bencode_read_list(dec, buf);

@ -23,11 +23,10 @@ namespace llarp
{ {
} }
using Ptr_t = std::unique_ptr< IMessage >; using Ptr_t = std::unique_ptr<IMessage>;
virtual bool virtual bool
HandleMessage(struct llarp_dht_context* dht, HandleMessage(struct llarp_dht_context* dht, std::vector<Ptr_t>& replies) const = 0;
std::vector< Ptr_t >& replies) const = 0;
virtual bool virtual bool
BEncode(llarp_buffer_t* buf) const = 0; BEncode(llarp_buffer_t* buf) const = 0;
@ -44,9 +43,8 @@ namespace llarp
DecodeMessage(const Key_t& from, llarp_buffer_t* buf, bool relayed = false); DecodeMessage(const Key_t& from, llarp_buffer_t* buf, bool relayed = false);
bool bool
DecodeMesssageList(Key_t from, llarp_buffer_t* buf, DecodeMesssageList(
std::vector< IMessage::Ptr_t >& dst, Key_t from, llarp_buffer_t* buf, std::vector<IMessage::Ptr_t>& dst, bool relayed = false);
bool relayed = false);
} // namespace dht } // namespace dht
} // namespace llarp } // namespace llarp

@ -12,7 +12,7 @@ namespace llarp
/// H /// H
ShortHash m_Hash; ShortHash m_Hash;
/// K /// K
std::vector< RouterID > m_Keys; std::vector<RouterID> m_Keys;
/// N /// N
uint64_t m_NumberOfEntries; uint64_t m_NumberOfEntries;
/// O /// O

@ -16,20 +16,19 @@ namespace llarp
{ {
bool read = false; bool read = false;
if(!BEncodeMaybeReadDictEntry("N", tagName, read, k, val)) if (!BEncodeMaybeReadDictEntry("N", tagName, read, k, val))
return false; return false;
if(!BEncodeMaybeReadDictInt("O", relayOrder, read, k, val)) if (!BEncodeMaybeReadDictInt("O", relayOrder, read, k, val))
return false; return false;
if(!BEncodeMaybeReadDictEntry("S", location, read, k, val)) if (!BEncodeMaybeReadDictEntry("S", location, read, k, val))
return false; return false;
if(!BEncodeMaybeReadDictInt("T", txID, read, k, val)) if (!BEncodeMaybeReadDictInt("T", txID, read, k, val))
return false; return false;
if(!BEncodeMaybeVerifyVersion("V", version, LLARP_PROTO_VERSION, read, k, if (!BEncodeMaybeVerifyVersion("V", version, LLARP_PROTO_VERSION, read, k, val))
val))
return false; return false;
return read; return read;
@ -38,36 +37,36 @@ namespace llarp
bool bool
FindIntroMessage::BEncode(llarp_buffer_t* buf) const FindIntroMessage::BEncode(llarp_buffer_t* buf) const
{ {
if(!bencode_start_dict(buf)) if (!bencode_start_dict(buf))
return false; return false;
// message id // message id
if(!BEncodeWriteDictMsgType(buf, "A", "F")) if (!BEncodeWriteDictMsgType(buf, "A", "F"))
return false; return false;
if(tagName.Empty()) if (tagName.Empty())
{ {
// relay order // relay order
if(!BEncodeWriteDictInt("O", relayOrder, buf)) if (!BEncodeWriteDictInt("O", relayOrder, buf))
return false; return false;
// service address // service address
if(!BEncodeWriteDictEntry("S", location, buf)) if (!BEncodeWriteDictEntry("S", location, buf))
return false; return false;
} }
else else
{ {
if(!BEncodeWriteDictEntry("N", tagName, buf)) if (!BEncodeWriteDictEntry("N", tagName, buf))
return false; return false;
// relay order // relay order
if(!BEncodeWriteDictInt("O", relayOrder, buf)) if (!BEncodeWriteDictInt("O", relayOrder, buf))
return false; return false;
} }
// txid // txid
if(!BEncodeWriteDictInt("T", txID, buf)) if (!BEncodeWriteDictInt("T", txID, buf))
return false; return false;
// protocol version // protocol version
if(!BEncodeWriteDictInt("V", LLARP_PROTO_VERSION, buf)) if (!BEncodeWriteDictInt("V", LLARP_PROTO_VERSION, buf))
return false; return false;
return bencode_end(buf); return bencode_end(buf);
@ -75,20 +74,20 @@ namespace llarp
bool bool
FindIntroMessage::HandleMessage( FindIntroMessage::HandleMessage(
llarp_dht_context* ctx, std::vector< IMessage::Ptr_t >& replies) const llarp_dht_context* ctx, std::vector<IMessage::Ptr_t>& replies) const
{ {
auto& dht = *ctx->impl; auto& dht = *ctx->impl;
if(dht.pendingIntrosetLookups().HasPendingLookupFrom(TXOwner{From, txID})) if (dht.pendingIntrosetLookups().HasPendingLookupFrom(TXOwner{From, txID}))
{ {
llarp::LogWarn("duplicate FIM from ", From, " txid=", txID); llarp::LogWarn("duplicate FIM from ", From, " txid=", txID);
return false; return false;
} }
if(not tagName.Empty()) if (not tagName.Empty())
return false; return false;
// bad request (request for zero-key) // bad request (request for zero-key)
if(location.IsZero()) if (location.IsZero())
{ {
// we dont got it // we dont got it
replies.emplace_back(new GotIntroMessage({}, txID)); replies.emplace_back(new GotIntroMessage({}, txID));
@ -96,35 +95,34 @@ namespace llarp
} }
// we are relaying this message for e.g. a client // we are relaying this message for e.g. a client
if(relayed) if (relayed)
{ {
if(relayOrder >= IntroSetStorageRedundancy) if (relayOrder >= IntroSetStorageRedundancy)
{ {
llarp::LogWarn("Invalid relayOrder received: ", relayOrder); llarp::LogWarn("Invalid relayOrder received: ", relayOrder);
replies.emplace_back(new GotIntroMessage({}, txID)); replies.emplace_back(new GotIntroMessage({}, txID));
return true; return true;
} }
auto closestRCs = dht.GetRouter()->nodedb()->FindClosestTo( auto closestRCs =
location, IntroSetStorageRedundancy); dht.GetRouter()->nodedb()->FindClosestTo(location, IntroSetStorageRedundancy);
if(closestRCs.size() <= relayOrder) if (closestRCs.size() <= relayOrder)
{ {
llarp::LogWarn("Can't fulfill FindIntro for relayOrder: ", llarp::LogWarn("Can't fulfill FindIntro for relayOrder: ", relayOrder);
relayOrder);
replies.emplace_back(new GotIntroMessage({}, txID)); replies.emplace_back(new GotIntroMessage({}, txID));
return true; return true;
} }
const auto& entry = closestRCs[relayOrder]; const auto& entry = closestRCs[relayOrder];
Key_t peer = Key_t(entry.pubkey); Key_t peer = Key_t(entry.pubkey);
dht.LookupIntroSetForPath(location, txID, pathID, peer, 0); dht.LookupIntroSetForPath(location, txID, pathID, peer, 0);
} }
else else
{ {
// we should have this value if introset was propagated properly // we should have this value if introset was propagated properly
const auto maybe = dht.GetIntroSetByLocation(location); const auto maybe = dht.GetIntroSetByLocation(location);
if(maybe.has_value()) if (maybe.has_value())
{ {
replies.emplace_back(new GotIntroMessage({maybe.value()}, txID)); replies.emplace_back(new GotIntroMessage({maybe.value()}, txID));
} }

@ -14,14 +14,13 @@ namespace llarp
{ {
Key_t location; Key_t location;
llarp::service::Tag tagName; llarp::service::Tag tagName;
uint64_t txID = 0; uint64_t txID = 0;
bool relayed = false; bool relayed = false;
uint64_t relayOrder = 0; uint64_t relayOrder = 0;
FindIntroMessage(const Key_t& from, bool relay, uint64_t order) FindIntroMessage(const Key_t& from, bool relay, uint64_t order) : IMessage(from)
: IMessage(from)
{ {
relayed = relay; relayed = relay;
relayOrder = order; relayOrder = order;
} }
@ -30,8 +29,7 @@ namespace llarp
{ {
} }
explicit FindIntroMessage(uint64_t txid, const Key_t& addr, explicit FindIntroMessage(uint64_t txid, const Key_t& addr, uint64_t order)
uint64_t order)
: IMessage({}), location(addr), txID(txid), relayOrder(order) : IMessage({}), location(addr), txID(txid), relayOrder(order)
{ {
tagName.Zero(); tagName.Zero();
@ -46,8 +44,7 @@ namespace llarp
DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) override; DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) override;
bool bool
HandleMessage(llarp_dht_context* ctx, HandleMessage(llarp_dht_context* ctx, std::vector<IMessage::Ptr_t>& replies) const override;
std::vector< IMessage::Ptr_t >& replies) const override;
}; };
} // namespace dht } // namespace dht
} // namespace llarp } // namespace llarp

@ -15,21 +15,18 @@ namespace llarp
{ {
bool bool
RelayedFindRouterMessage::HandleMessage( RelayedFindRouterMessage::HandleMessage(
llarp_dht_context *ctx, llarp_dht_context* ctx, std::vector<std::unique_ptr<IMessage>>& replies) const
std::vector< std::unique_ptr< IMessage > > &replies) const
{ {
auto &dht = *ctx->impl; auto& dht = *ctx->impl;
/// lookup for us, send an immeidate reply /// lookup for us, send an immeidate reply
const Key_t us = dht.OurKey(); const Key_t us = dht.OurKey();
const Key_t k{targetKey}; const Key_t k{targetKey};
if(k == us) if (k == us)
{ {
auto path = auto path = dht.GetRouter()->pathContext().GetByUpstream(targetKey, pathID);
dht.GetRouter()->pathContext().GetByUpstream(targetKey, pathID); if (path)
if(path)
{ {
replies.emplace_back( replies.emplace_back(new GotRouterMessage(k, txid, {dht.GetRouter()->rc()}, false));
new GotRouterMessage(k, txid, {dht.GetRouter()->rc()}, false));
return true; return true;
} }
return false; return false;
@ -37,7 +34,7 @@ namespace llarp
Key_t peer; Key_t peer;
// check if we know this in our nodedb first // check if we know this in our nodedb first
if(not dht.GetRouter()->ConnectionToRouterAllowed(targetKey)) if (not dht.GetRouter()->ConnectionToRouterAllowed(targetKey))
{ {
// explicitly disallowed by network // explicitly disallowed by network
replies.emplace_back(new GotRouterMessage(k, txid, {}, false)); replies.emplace_back(new GotRouterMessage(k, txid, {}, false));
@ -45,7 +42,7 @@ namespace llarp
} }
// check netdb // check netdb
const auto rc = dht.GetRouter()->nodedb()->FindClosestTo(k); const auto rc = dht.GetRouter()->nodedb()->FindClosestTo(k);
if(rc.pubkey == targetKey) if (rc.pubkey == targetKey)
{ {
replies.emplace_back(new GotRouterMessage(k, txid, {rc}, false)); replies.emplace_back(new GotRouterMessage(k, txid, {rc}, false));
return true; return true;
@ -59,89 +56,89 @@ namespace llarp
FindRouterMessage::~FindRouterMessage() = default; FindRouterMessage::~FindRouterMessage() = default;
bool bool
FindRouterMessage::BEncode(llarp_buffer_t *buf) const FindRouterMessage::BEncode(llarp_buffer_t* buf) const
{ {
if(!bencode_start_dict(buf)) if (!bencode_start_dict(buf))
return false; return false;
// message type // message type
if(!bencode_write_bytestring(buf, "A", 1)) if (!bencode_write_bytestring(buf, "A", 1))
return false; return false;
if(!bencode_write_bytestring(buf, "R", 1)) if (!bencode_write_bytestring(buf, "R", 1))
return false; return false;
// exploritory or not? // exploritory or not?
if(!bencode_write_bytestring(buf, "E", 1)) if (!bencode_write_bytestring(buf, "E", 1))
return false; return false;
if(!bencode_write_uint64(buf, exploritory ? 1 : 0)) if (!bencode_write_uint64(buf, exploritory ? 1 : 0))
return false; return false;
// iterative or not? // iterative or not?
if(!bencode_write_bytestring(buf, "I", 1)) if (!bencode_write_bytestring(buf, "I", 1))
return false; return false;
if(!bencode_write_uint64(buf, iterative ? 1 : 0)) if (!bencode_write_uint64(buf, iterative ? 1 : 0))
return false; return false;
// key // key
if(!bencode_write_bytestring(buf, "K", 1)) if (!bencode_write_bytestring(buf, "K", 1))
return false; return false;
if(!bencode_write_bytestring(buf, targetKey.data(), targetKey.size())) if (!bencode_write_bytestring(buf, targetKey.data(), targetKey.size()))
return false; return false;
// txid // txid
if(!bencode_write_bytestring(buf, "T", 1)) if (!bencode_write_bytestring(buf, "T", 1))
return false; return false;
if(!bencode_write_uint64(buf, txid)) if (!bencode_write_uint64(buf, txid))
return false; return false;
// version // version
if(!bencode_write_bytestring(buf, "V", 1)) if (!bencode_write_bytestring(buf, "V", 1))
return false; return false;
if(!bencode_write_uint64(buf, version)) if (!bencode_write_uint64(buf, version))
return false; return false;
return bencode_end(buf); return bencode_end(buf);
} }
bool bool
FindRouterMessage::DecodeKey(const llarp_buffer_t &key, llarp_buffer_t *val) FindRouterMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val)
{ {
llarp_buffer_t strbuf; llarp_buffer_t strbuf;
if(key == "E") if (key == "E")
{ {
uint64_t result; uint64_t result;
if(!bencode_read_integer(val, &result)) if (!bencode_read_integer(val, &result))
return false; return false;
exploritory = result != 0; exploritory = result != 0;
return true; return true;
} }
if(key == "I") if (key == "I")
{ {
uint64_t result; uint64_t result;
if(!bencode_read_integer(val, &result)) if (!bencode_read_integer(val, &result))
return false; return false;
iterative = result != 0; iterative = result != 0;
return true; return true;
} }
if(key == "K") if (key == "K")
{ {
if(!bencode_read_string(val, &strbuf)) if (!bencode_read_string(val, &strbuf))
return false; return false;
if(strbuf.sz != targetKey.size()) if (strbuf.sz != targetKey.size())
return false; return false;
std::copy(strbuf.base, strbuf.base + targetKey.SIZE, targetKey.begin()); std::copy(strbuf.base, strbuf.base + targetKey.SIZE, targetKey.begin());
return true; return true;
} }
if(key == "T") if (key == "T")
{ {
return bencode_read_integer(val, &txid); return bencode_read_integer(val, &txid);
} }
if(key == "V") if (key == "V")
{ {
return bencode_read_integer(val, &version); return bencode_read_integer(val, &version);
} }
@ -150,37 +147,32 @@ namespace llarp
bool bool
FindRouterMessage::HandleMessage( FindRouterMessage::HandleMessage(
llarp_dht_context *ctx, llarp_dht_context* ctx, std::vector<std::unique_ptr<IMessage>>& replies) const
std::vector< std::unique_ptr< IMessage > > &replies) const
{ {
auto &dht = *ctx->impl; auto& dht = *ctx->impl;
auto router = dht.GetRouter(); auto router = dht.GetRouter();
router->NotifyRouterEvent< tooling::FindRouterReceivedEvent >( router->NotifyRouterEvent<tooling::FindRouterReceivedEvent>(router->pubkey(), this);
router->pubkey(),
this);
if(!dht.AllowTransit()) if (!dht.AllowTransit())
{ {
llarp::LogWarn("Got DHT lookup from ", From, llarp::LogWarn("Got DHT lookup from ", From, " when we are not allowing dht transit");
" when we are not allowing dht transit");
return false; return false;
} }
if(dht.pendingRouterLookups().HasPendingLookupFrom({From, txid})) if (dht.pendingRouterLookups().HasPendingLookupFrom({From, txid}))
{ {
llarp::LogWarn("Duplicate FRM from ", From, " txid=", txid); llarp::LogWarn("Duplicate FRM from ", From, " txid=", txid);
return false; return false;
} }
RouterContact found; RouterContact found;
if(targetKey.IsZero()) if (targetKey.IsZero())
{ {
llarp::LogError("invalid FRM from ", From, " key is zero"); llarp::LogError("invalid FRM from ", From, " key is zero");
return false; return false;
} }
const Key_t k(targetKey); const Key_t k(targetKey);
if(exploritory) if (exploritory)
return dht.HandleExploritoryRouterLookup(From, txid, targetKey, return dht.HandleExploritoryRouterLookup(From, txid, targetKey, replies);
replies);
dht.LookupRouterRelayed(From, txid, k, !iterative, replies); dht.LookupRouterRelayed(From, txid, k, !iterative, replies);
return true; return true;
} }

@ -35,13 +35,12 @@ namespace llarp
bool bool
HandleMessage( HandleMessage(
llarp_dht_context* ctx, llarp_dht_context* ctx, std::vector<std::unique_ptr<IMessage>>& replies) const override;
std::vector< std::unique_ptr< IMessage > >& replies) const override;
RouterID targetKey; RouterID targetKey;
bool iterative = false; bool iterative = false;
bool exploritory = false; bool exploritory = false;
uint64_t txid = 0; uint64_t txid = 0;
uint64_t version = 0; uint64_t version = 0;
}; };
@ -56,8 +55,7 @@ namespace llarp
/// the path of the result /// the path of the result
/// TODO: smart path expiration logic needs to be implemented /// TODO: smart path expiration logic needs to be implemented
bool bool
HandleMessage(llarp_dht_context* ctx, HandleMessage(llarp_dht_context* ctx, std::vector<IMessage::Ptr_t>& replies) const override;
std::vector< IMessage::Ptr_t >& replies) const override;
}; };
} // namespace dht } // namespace dht
} // namespace llarp } // namespace llarp

@ -13,28 +13,27 @@ namespace llarp
{ {
namespace dht namespace dht
{ {
GotIntroMessage::GotIntroMessage( GotIntroMessage::GotIntroMessage(std::vector<service::EncryptedIntroSet> results, uint64_t tx)
std::vector< service::EncryptedIntroSet > results, uint64_t tx)
: IMessage({}), found(std::move(results)), txid(tx) : IMessage({}), found(std::move(results)), txid(tx)
{ {
} }
bool bool
GotIntroMessage::HandleMessage( GotIntroMessage::HandleMessage(
llarp_dht_context *ctx, llarp_dht_context* ctx, std::vector<std::unique_ptr<IMessage>>& /*replies*/) const
std::vector< std::unique_ptr< IMessage > > & /*replies*/) const
{ {
auto &dht = *ctx->impl; auto& dht = *ctx->impl;
auto *router = dht.GetRouter(); auto* router = dht.GetRouter();
router->NotifyRouterEvent< tooling::GotIntroReceivedEvent >( router->NotifyRouterEvent<tooling::GotIntroReceivedEvent>(
router->pubkey(), Key_t(From.data()), router->pubkey(),
Key_t(From.data()),
(found.size() > 0 ? found[0] : llarp::service::EncryptedIntroSet{}), (found.size() > 0 ? found[0] : llarp::service::EncryptedIntroSet{}),
txid); txid);
for(const auto &introset : found) for (const auto& introset : found)
{ {
if(!introset.Verify(dht.Now())) if (!introset.Verify(dht.Now()))
{ {
LogWarn( LogWarn(
"Invalid introset while handling direct GotIntro " "Invalid introset while handling direct GotIntro "
@ -45,14 +44,12 @@ namespace llarp
} }
TXOwner owner(From, txid); TXOwner owner(From, txid);
auto serviceLookup = auto serviceLookup = dht.pendingIntrosetLookups().GetPendingLookupFrom(owner);
dht.pendingIntrosetLookups().GetPendingLookupFrom(owner); if (serviceLookup)
if(serviceLookup)
{ {
if(not found.empty()) if (not found.empty())
{ {
dht.pendingIntrosetLookups().Found(owner, serviceLookup->target, dht.pendingIntrosetLookups().Found(owner, serviceLookup->target, found);
found);
} }
else else
{ {
@ -66,16 +63,14 @@ namespace llarp
bool bool
RelayedGotIntroMessage::HandleMessage( RelayedGotIntroMessage::HandleMessage(
llarp_dht_context *ctx, llarp_dht_context* ctx,
__attribute__((unused)) __attribute__((unused)) std::vector<std::unique_ptr<IMessage>>& replies) const
std::vector< std::unique_ptr< IMessage > > &replies) const
{ {
// TODO: implement me better? // TODO: implement me better?
auto pathset = auto pathset = ctx->impl->GetRouter()->pathContext().GetLocalPathSet(pathID);
ctx->impl->GetRouter()->pathContext().GetLocalPathSet(pathID); if (pathset)
if(pathset)
{ {
auto copy = std::make_shared< const RelayedGotIntroMessage >(*this); auto copy = std::make_shared<const RelayedGotIntroMessage>(*this);
return pathset->HandleGotIntroMessage(copy); return pathset->HandleGotIntroMessage(copy);
} }
LogWarn("No path for got intro message pathid=", pathID); LogWarn("No path for got intro message pathid=", pathID);
@ -83,47 +78,47 @@ namespace llarp
} }
bool bool
GotIntroMessage::DecodeKey(const llarp_buffer_t &key, llarp_buffer_t *buf) GotIntroMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf)
{ {
if(key == "I") if (key == "I")
{ {
return BEncodeReadList(found, buf); return BEncodeReadList(found, buf);
} }
if(key == "K") if (key == "K")
{ {
if(closer.has_value()) // duplicate key? if (closer.has_value()) // duplicate key?
return false; return false;
dht::Key_t K; dht::Key_t K;
if(not K.BDecode(buf)) if (not K.BDecode(buf))
return false; return false;
closer = K; closer = K;
return true; return true;
} }
bool read = false; bool read = false;
if(!BEncodeMaybeReadDictInt("T", txid, read, key, buf)) if (!BEncodeMaybeReadDictInt("T", txid, read, key, buf))
return false; return false;
if(!BEncodeMaybeReadDictInt("V", version, read, key, buf)) if (!BEncodeMaybeReadDictInt("V", version, read, key, buf))
return false; return false;
return read; return read;
} }
bool bool
GotIntroMessage::BEncode(llarp_buffer_t *buf) const GotIntroMessage::BEncode(llarp_buffer_t* buf) const
{ {
if(!bencode_start_dict(buf)) if (!bencode_start_dict(buf))
return false; return false;
if(!BEncodeWriteDictMsgType(buf, "A", "G")) if (!BEncodeWriteDictMsgType(buf, "A", "G"))
return false; return false;
if(!BEncodeWriteDictList("I", found, buf)) if (!BEncodeWriteDictList("I", found, buf))
return false; return false;
if(closer.has_value()) if (closer.has_value())
{ {
if(!BEncodeWriteDictEntry("K", closer.value(), buf)) if (!BEncodeWriteDictEntry("K", closer.value(), buf))
return false; return false;
} }
if(!BEncodeWriteDictInt("T", txid, buf)) if (!BEncodeWriteDictInt("T", txid, buf))
return false; return false;
if(!BEncodeWriteDictInt("V", version, buf)) if (!BEncodeWriteDictInt("V", version, buf))
return false; return false;
return bencode_end(buf); return bencode_end(buf);
} }

@ -16,21 +16,18 @@ namespace llarp
struct GotIntroMessage : public IMessage struct GotIntroMessage : public IMessage
{ {
/// the found introsets /// the found introsets
std::vector< service::EncryptedIntroSet > found; std::vector<service::EncryptedIntroSet> found;
/// txid /// txid
uint64_t txid = 0; uint64_t txid = 0;
/// the key of a router closer in keyspace if iterative lookup /// the key of a router closer in keyspace if iterative lookup
nonstd::optional< Key_t > closer; nonstd::optional<Key_t> closer;
GotIntroMessage(const Key_t& from) : IMessage(from) GotIntroMessage(const Key_t& from) : IMessage(from)
{ {
} }
GotIntroMessage(const GotIntroMessage& other) GotIntroMessage(const GotIntroMessage& other)
: IMessage(other.From) : IMessage(other.From), found(other.found), txid(other.txid), closer(other.closer)
, found(other.found)
, txid(other.txid)
, closer(other.closer)
{ {
version = other.version; version = other.version;
} }
@ -42,8 +39,7 @@ namespace llarp
} }
/// for recursive reply /// for recursive reply
GotIntroMessage(std::vector< service::EncryptedIntroSet > results, GotIntroMessage(std::vector<service::EncryptedIntroSet> results, uint64_t txid);
uint64_t txid);
~GotIntroMessage() override = default; ~GotIntroMessage() override = default;
@ -54,8 +50,7 @@ namespace llarp
DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) override; DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) override;
bool bool
HandleMessage(llarp_dht_context* ctx, HandleMessage(llarp_dht_context* ctx, std::vector<IMessage::Ptr_t>& replies) const override;
std::vector< IMessage::Ptr_t >& replies) const override;
}; };
struct RelayedGotIntroMessage final : public GotIntroMessage struct RelayedGotIntroMessage final : public GotIntroMessage
@ -65,11 +60,10 @@ namespace llarp
} }
bool bool
HandleMessage(llarp_dht_context* ctx, HandleMessage(llarp_dht_context* ctx, std::vector<IMessage::Ptr_t>& replies) const override;
std::vector< IMessage::Ptr_t >& replies) const override;
}; };
using GotIntroMessage_constptr = std::shared_ptr< const GotIntroMessage >; using GotIntroMessage_constptr = std::shared_ptr<const GotIntroMessage>;
} // namespace dht } // namespace dht
} // namespace llarp } // namespace llarp
#endif #endif

@ -14,67 +14,66 @@ namespace llarp
GotRouterMessage::~GotRouterMessage() = default; GotRouterMessage::~GotRouterMessage() = default;
bool bool
GotRouterMessage::BEncode(llarp_buffer_t *buf) const GotRouterMessage::BEncode(llarp_buffer_t* buf) const
{ {
if(not bencode_start_dict(buf)) if (not bencode_start_dict(buf))
return false; return false;
// message type // message type
if(not BEncodeWriteDictMsgType(buf, "A", "S")) if (not BEncodeWriteDictMsgType(buf, "A", "S"))
return false; return false;
if(closerTarget) if (closerTarget)
{ {
if(not BEncodeWriteDictEntry("K", *closerTarget, buf)) if (not BEncodeWriteDictEntry("K", *closerTarget, buf))
return false; return false;
} }
// near // near
if(not nearKeys.empty()) if (not nearKeys.empty())
{ {
if(not BEncodeWriteDictList("N", nearKeys, buf)) if (not BEncodeWriteDictList("N", nearKeys, buf))
return false; return false;
} }
if(not BEncodeWriteDictList("R", foundRCs, buf)) if (not BEncodeWriteDictList("R", foundRCs, buf))
return false; return false;
// txid // txid
if(not BEncodeWriteDictInt("T", txid, buf)) if (not BEncodeWriteDictInt("T", txid, buf))
return false; return false;
// version // version
if(not BEncodeWriteDictInt("V", version, buf)) if (not BEncodeWriteDictInt("V", version, buf))
return false; return false;
return bencode_end(buf); return bencode_end(buf);
} }
bool bool
GotRouterMessage::DecodeKey(const llarp_buffer_t &key, llarp_buffer_t *val) GotRouterMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val)
{ {
if(key == "K") if (key == "K")
{ {
if(closerTarget) // duplicate key? if (closerTarget) // duplicate key?
return false; return false;
closerTarget = std::make_unique< dht::Key_t >(); closerTarget = std::make_unique<dht::Key_t>();
return closerTarget->BDecode(val); return closerTarget->BDecode(val);
} }
if(key == "N") if (key == "N")
{ {
return BEncodeReadList(nearKeys, val); return BEncodeReadList(nearKeys, val);
} }
if(key == "R") if (key == "R")
{ {
return BEncodeReadList(foundRCs, val); return BEncodeReadList(foundRCs, val);
} }
if(key == "T") if (key == "T")
{ {
return bencode_read_integer(val, &txid); return bencode_read_integer(val, &txid);
} }
bool read = false; bool read = false;
if(!BEncodeMaybeVerifyVersion("V", version, LLARP_PROTO_VERSION, read, if (!BEncodeMaybeVerifyVersion("V", version, LLARP_PROTO_VERSION, read, key, val))
key, val))
return false; return false;
return read; return read;
@ -82,25 +81,23 @@ namespace llarp
bool bool
GotRouterMessage::HandleMessage( GotRouterMessage::HandleMessage(
llarp_dht_context *ctx, llarp_dht_context* ctx,
__attribute__((unused)) __attribute__((unused)) std::vector<std::unique_ptr<IMessage>>& replies) const
std::vector< std::unique_ptr< IMessage > > &replies) const
{ {
auto &dht = *ctx->impl; auto& dht = *ctx->impl;
if(relayed) if (relayed)
{ {
auto pathset = auto pathset = ctx->impl->GetRouter()->pathContext().GetLocalPathSet(pathID);
ctx->impl->GetRouter()->pathContext().GetLocalPathSet(pathID); auto copy = std::make_shared<const GotRouterMessage>(*this);
auto copy = std::make_shared< const GotRouterMessage >(*this);
return pathset && pathset->HandleGotRouterMessage(copy); return pathset && pathset->HandleGotRouterMessage(copy);
} }
// not relayed // not relayed
const TXOwner owner(From, txid); const TXOwner owner(From, txid);
if(dht.pendingExploreLookups().HasPendingLookupFrom(owner)) if (dht.pendingExploreLookups().HasPendingLookupFrom(owner))
{ {
LogDebug("got ", nearKeys.size(), " results in GRM for explore"); LogDebug("got ", nearKeys.size(), " results in GRM for explore");
if(nearKeys.empty()) if (nearKeys.empty())
dht.pendingExploreLookups().NotFound(owner, closerTarget); dht.pendingExploreLookups().NotFound(owner, closerTarget);
else else
{ {
@ -109,28 +106,27 @@ namespace llarp
return true; return true;
} }
// not explore lookup // not explore lookup
if(dht.pendingRouterLookups().HasPendingLookupFrom(owner)) if (dht.pendingRouterLookups().HasPendingLookupFrom(owner))
{ {
LogDebug("got ", foundRCs.size(), " results in GRM for lookup"); LogDebug("got ", foundRCs.size(), " results in GRM for lookup");
if(foundRCs.empty()) if (foundRCs.empty())
dht.pendingRouterLookups().NotFound(owner, closerTarget); dht.pendingRouterLookups().NotFound(owner, closerTarget);
else if(foundRCs[0].pubkey.IsZero()) else if (foundRCs[0].pubkey.IsZero())
return false; return false;
else else
dht.pendingRouterLookups().Found(owner, foundRCs[0].pubkey, foundRCs); dht.pendingRouterLookups().Found(owner, foundRCs[0].pubkey, foundRCs);
return true; return true;
} }
// store if valid // store if valid
for(const auto &rc : foundRCs) for (const auto& rc : foundRCs)
{ {
if(not dht.GetRouter()->rcLookupHandler().CheckRC(rc)) if (not dht.GetRouter()->rcLookupHandler().CheckRC(rc))
return false; return false;
if(txid == 0) // txid == 0 on gossip if (txid == 0) // txid == 0 on gossip
{ {
LogWarn("Received Gossiped RC, generating RCGossipReceivedEvent"); LogWarn("Received Gossiped RC, generating RCGossipReceivedEvent");
auto *router = dht.GetRouter(); auto* router = dht.GetRouter();
router->NotifyRouterEvent< tooling::RCGossipReceivedEvent >( router->NotifyRouterEvent<tooling::RCGossipReceivedEvent>(router->pubkey(), rc);
router->pubkey(), rc);
router->GossipRCIfNeeded(rc); router->GossipRCIfNeeded(rc);
} }
} }

@ -13,38 +13,27 @@ namespace llarp
{ {
struct GotRouterMessage final : public IMessage struct GotRouterMessage final : public IMessage
{ {
GotRouterMessage(const Key_t& from, bool tunneled) GotRouterMessage(const Key_t& from, bool tunneled) : IMessage(from), relayed(tunneled)
: IMessage(from), relayed(tunneled)
{ {
} }
GotRouterMessage(const Key_t& from, uint64_t id, GotRouterMessage(
const std::vector< RouterContact >& results, const Key_t& from, uint64_t id, const std::vector<RouterContact>& results, bool tunneled)
bool tunneled)
: IMessage(from), foundRCs(results), txid(id), relayed(tunneled) : IMessage(from), foundRCs(results), txid(id), relayed(tunneled)
{ {
} }
GotRouterMessage(const Key_t& from, const Key_t& closer, uint64_t id, GotRouterMessage(const Key_t& from, const Key_t& closer, uint64_t id, bool tunneled)
bool tunneled) : IMessage(from), closerTarget(new Key_t(closer)), txid(id), relayed(tunneled)
: IMessage(from)
, closerTarget(new Key_t(closer))
, txid(id)
, relayed(tunneled)
{ {
} }
GotRouterMessage(uint64_t id, std::vector< RouterID > _near, GotRouterMessage(uint64_t id, std::vector<RouterID> _near, bool tunneled)
bool tunneled) : IMessage({}), nearKeys(std::move(_near)), txid(id), relayed(tunneled)
: IMessage({})
, nearKeys(std::move(_near))
, txid(id)
, relayed(tunneled)
{ {
} }
/// gossip message /// gossip message
GotRouterMessage(const RouterContact rc) GotRouterMessage(const RouterContact rc) : IMessage({}), foundRCs({rc}), txid(0)
: IMessage({}), foundRCs({rc}), txid(0)
{ {
version = LLARP_PROTO_VERSION; version = LLARP_PROTO_VERSION;
} }
@ -70,17 +59,16 @@ namespace llarp
bool bool
HandleMessage( HandleMessage(
llarp_dht_context* ctx, llarp_dht_context* ctx, std::vector<std::unique_ptr<IMessage>>& replies) const override;
std::vector< std::unique_ptr< IMessage > >& replies) const override;
std::vector< RouterContact > foundRCs; std::vector<RouterContact> foundRCs;
std::vector< RouterID > nearKeys; std::vector<RouterID> nearKeys;
std::unique_ptr< Key_t > closerTarget; std::unique_ptr<Key_t> closerTarget;
uint64_t txid = 0; uint64_t txid = 0;
bool relayed = false; bool relayed = false;
}; };
using GotRouterMessage_constptr = std::shared_ptr< const GotRouterMessage >; using GotRouterMessage_constptr = std::shared_ptr<const GotRouterMessage>;
} // namespace dht } // namespace dht
} // namespace llarp } // namespace llarp
#endif #endif

@ -14,40 +14,39 @@ namespace llarp
namespace dht namespace dht
{ {
const uint64_t PublishIntroMessage::MaxPropagationDepth = 5; const uint64_t PublishIntroMessage::MaxPropagationDepth = 5;
PublishIntroMessage::~PublishIntroMessage() = default; PublishIntroMessage::~PublishIntroMessage() = default;
bool bool
PublishIntroMessage::DecodeKey(const llarp_buffer_t &key, PublishIntroMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val)
llarp_buffer_t *val)
{ {
bool read = false; bool read = false;
if(!BEncodeMaybeReadDictEntry("I", introset, read, key, val)) if (!BEncodeMaybeReadDictEntry("I", introset, read, key, val))
return false; return false;
if(read) if (read)
return true; return true;
if(!BEncodeMaybeReadDictInt("O", relayOrder, read, key, val)) if (!BEncodeMaybeReadDictInt("O", relayOrder, read, key, val))
return false; return false;
if(read) if (read)
return true; return true;
uint64_t relayedInt = (relayed ? 1 : 0); uint64_t relayedInt = (relayed ? 1 : 0);
if(!BEncodeMaybeReadDictInt("R", relayedInt, read, key, val)) if (!BEncodeMaybeReadDictInt("R", relayedInt, read, key, val))
return false; return false;
if(read) if (read)
{ {
relayed = relayedInt; relayed = relayedInt;
return true; return true;
} }
if(!BEncodeMaybeReadDictInt("T", txID, read, key, val)) if (!BEncodeMaybeReadDictInt("T", txID, read, key, val))
return false; return false;
if(read) if (read)
return true; return true;
if(!BEncodeMaybeReadDictInt("V", version, read, key, val)) if (!BEncodeMaybeReadDictInt("V", version, read, key, val))
return false; return false;
if(read) if (read)
return true; return true;
return false; return false;
@ -55,61 +54,58 @@ namespace llarp
bool bool
PublishIntroMessage::HandleMessage( PublishIntroMessage::HandleMessage(
llarp_dht_context *ctx, llarp_dht_context* ctx, std::vector<std::unique_ptr<IMessage>>& replies) const
std::vector< std::unique_ptr< IMessage > > &replies) const
{ {
const auto now = ctx->impl->Now(); const auto now = ctx->impl->Now();
const llarp::dht::Key_t addr(introset.derivedSigningKey); const llarp::dht::Key_t addr(introset.derivedSigningKey);
const auto keyStr = addr.ToHex(); const auto keyStr = addr.ToHex();
auto router = ctx->impl->GetRouter(); auto router = ctx->impl->GetRouter();
router->NotifyRouterEvent< tooling::PubIntroReceivedEvent >( router->NotifyRouterEvent<tooling::PubIntroReceivedEvent>(
router->pubkey(), Key_t(relayed ? router->pubkey() : From.data()), router->pubkey(),
addr, txID, relayOrder); Key_t(relayed ? router->pubkey() : From.data()),
addr,
auto &dht = *ctx->impl; txID,
if(!introset.Verify(now)) relayOrder);
auto& dht = *ctx->impl;
if (!introset.Verify(now))
{ {
llarp::LogWarn("Received PublishIntroMessage with invalid introset: ", llarp::LogWarn("Received PublishIntroMessage with invalid introset: ", introset);
introset);
// don't propogate or store // don't propogate or store
replies.emplace_back(new GotIntroMessage({}, txID)); replies.emplace_back(new GotIntroMessage({}, txID));
return true; return true;
} }
if(introset.IsExpired(now + llarp::service::MAX_INTROSET_TIME_DELTA)) if (introset.IsExpired(now + llarp::service::MAX_INTROSET_TIME_DELTA))
{ {
// don't propogate or store // don't propogate or store
llarp::LogWarn("Received PublishIntroMessage with expired Introset: ", llarp::LogWarn("Received PublishIntroMessage with expired Introset: ", introset);
introset);
replies.emplace_back(new GotIntroMessage({}, txID)); replies.emplace_back(new GotIntroMessage({}, txID));
return true; return true;
} }
// identify closest 4 routers // identify closest 4 routers
auto closestRCs = dht.GetRouter()->nodedb()->FindClosestTo( auto closestRCs = dht.GetRouter()->nodedb()->FindClosestTo(addr, IntroSetStorageRedundancy);
addr, IntroSetStorageRedundancy); if (closestRCs.size() != IntroSetStorageRedundancy)
if(closestRCs.size() != IntroSetStorageRedundancy)
{ {
llarp::LogWarn("Received PublishIntroMessage but only know ", llarp::LogWarn("Received PublishIntroMessage but only know ", closestRCs.size(), " nodes");
closestRCs.size(), " nodes");
replies.emplace_back(new GotIntroMessage({}, txID)); replies.emplace_back(new GotIntroMessage({}, txID));
return true; return true;
} }
const auto &us = dht.OurKey(); const auto& us = dht.OurKey();
// function to identify the closest 4 routers we know of for this introset // function to identify the closest 4 routers we know of for this introset
auto propagateIfNotUs = [&](size_t index) { auto propagateIfNotUs = [&](size_t index) {
assert(index < IntroSetStorageRedundancy); assert(index < IntroSetStorageRedundancy);
const auto &rc = closestRCs[index]; const auto& rc = closestRCs[index];
const Key_t peer{rc.pubkey}; const Key_t peer{rc.pubkey};
if(peer == us) if (peer == us)
{ {
llarp::LogInfo("we are peer ", index, llarp::LogInfo("we are peer ", index, " so storing instead of propagating");
" so storing instead of propagating");
dht.services()->PutNode(introset); dht.services()->PutNode(introset);
replies.emplace_back(new GotIntroMessage({introset}, txID)); replies.emplace_back(new GotIntroMessage({introset}, txID));
@ -117,7 +113,7 @@ namespace llarp
else else
{ {
llarp::LogInfo("propagating to peer ", index); llarp::LogInfo("propagating to peer ", index);
if(relayed) if (relayed)
{ {
dht.PropagateLocalIntroSet(pathID, txID, introset, peer, 0); dht.PropagateLocalIntroSet(pathID, txID, introset, peer, 0);
} }
@ -128,29 +124,26 @@ namespace llarp
} }
}; };
if(relayed) if (relayed)
{ {
if(relayOrder >= IntroSetStorageRedundancy) if (relayOrder >= IntroSetStorageRedundancy)
{ {
llarp::LogWarn( llarp::LogWarn("Received PublishIntroMessage with invalid relayOrder: ", relayOrder);
"Received PublishIntroMessage with invalid relayOrder: ",
relayOrder);
replies.emplace_back(new GotIntroMessage({}, txID)); replies.emplace_back(new GotIntroMessage({}, txID));
return true; return true;
} }
llarp::LogInfo("Relaying PublishIntroMessage for ", keyStr, llarp::LogInfo("Relaying PublishIntroMessage for ", keyStr, ", txid=", txID);
", txid=", txID);
propagateIfNotUs(relayOrder); propagateIfNotUs(relayOrder);
} }
else else
{ {
int candidateNumber = -1; int candidateNumber = -1;
int index = 0; int index = 0;
for(const auto &rc : closestRCs) for (const auto& rc : closestRCs)
{ {
if(rc.pubkey == dht.OurKey()) if (rc.pubkey == dht.OurKey())
{ {
candidateNumber = index; candidateNumber = index;
break; break;
@ -158,10 +151,15 @@ namespace llarp
++index; ++index;
} }
if(candidateNumber >= 0) if (candidateNumber >= 0)
{ {
LogInfo("Received PubIntro for ", keyStr, ", txid=", txID, LogInfo(
" and we are candidate ", candidateNumber); "Received PubIntro for ",
keyStr,
", txid=",
txID,
" and we are candidate ",
candidateNumber);
dht.services()->PutNode(introset); dht.services()->PutNode(introset);
replies.emplace_back(new GotIntroMessage({introset}, txID)); replies.emplace_back(new GotIntroMessage({introset}, txID));
} }
@ -170,7 +168,11 @@ namespace llarp
LogWarn( LogWarn(
"!!! Received PubIntro with relayed==false but we aren't" "!!! Received PubIntro with relayed==false but we aren't"
" candidate, intro derived key: ", " candidate, intro derived key: ",
keyStr, ", txid=", txID, ", message from: ", From); keyStr,
", txid=",
txID,
", message from: ",
From);
} }
} }
@ -178,21 +180,21 @@ namespace llarp
} }
bool bool
PublishIntroMessage::BEncode(llarp_buffer_t *buf) const PublishIntroMessage::BEncode(llarp_buffer_t* buf) const
{ {
if(!bencode_start_dict(buf)) if (!bencode_start_dict(buf))
return false; return false;
if(!BEncodeWriteDictMsgType(buf, "A", "I")) if (!BEncodeWriteDictMsgType(buf, "A", "I"))
return false; return false;
if(!BEncodeWriteDictEntry("I", introset, buf)) if (!BEncodeWriteDictEntry("I", introset, buf))
return false; return false;
if(!BEncodeWriteDictInt("O", relayOrder, buf)) if (!BEncodeWriteDictInt("O", relayOrder, buf))
return false; return false;
if(!BEncodeWriteDictInt("R", relayed, buf)) if (!BEncodeWriteDictInt("R", relayed, buf))
return false; return false;
if(!BEncodeWriteDictInt("T", txID, buf)) if (!BEncodeWriteDictInt("T", txID, buf))
return false; return false;
if(!BEncodeWriteDictInt("V", LLARP_PROTO_VERSION, buf)) if (!BEncodeWriteDictInt("V", LLARP_PROTO_VERSION, buf))
return false; return false;
return bencode_end(buf); return bencode_end(buf);
} }

@ -14,21 +14,19 @@ namespace llarp
{ {
static const uint64_t MaxPropagationDepth; static const uint64_t MaxPropagationDepth;
llarp::service::EncryptedIntroSet introset; llarp::service::EncryptedIntroSet introset;
bool relayed = false; bool relayed = false;
uint64_t relayOrder = 0; uint64_t relayOrder = 0;
uint64_t txID = 0; uint64_t txID = 0;
PublishIntroMessage(const Key_t& from, bool relayed_) PublishIntroMessage(const Key_t& from, bool relayed_) : IMessage(from), relayed(relayed_)
: IMessage(from), relayed(relayed_)
{ {
} }
PublishIntroMessage(const llarp::service::EncryptedIntroSet& introset_, PublishIntroMessage(
uint64_t tx, bool relayed_, uint64_t relayOrder_) const llarp::service::EncryptedIntroSet& introset_,
: IMessage({}) uint64_t tx,
, introset(introset_) bool relayed_,
, relayed(relayed_) uint64_t relayOrder_)
, relayOrder(relayOrder_) : IMessage({}), introset(introset_), relayed(relayed_), relayOrder(relayOrder_), txID(tx)
, txID(tx)
{ {
} }
@ -42,8 +40,7 @@ namespace llarp
bool bool
HandleMessage( HandleMessage(
llarp_dht_context* ctx, llarp_dht_context* ctx, std::vector<std::unique_ptr<IMessage>>& replies) const override;
std::vector< std::unique_ptr< IMessage > >& replies) const override;
}; };
} // namespace dht } // namespace dht
} // namespace llarp } // namespace llarp

@ -13,21 +13,22 @@ namespace llarp
namespace dht namespace dht
{ {
PublishServiceJob::PublishServiceJob( PublishServiceJob::PublishServiceJob(
const TXOwner &asker, const service::EncryptedIntroSet &introset_, const TXOwner& asker,
AbstractContext *ctx, uint64_t relayOrder_) const service::EncryptedIntroSet& introset_,
: TX< TXOwner, service::EncryptedIntroSet >(asker, asker, ctx) AbstractContext* ctx,
uint64_t relayOrder_)
: TX<TXOwner, service::EncryptedIntroSet>(asker, asker, ctx)
, relayOrder(relayOrder_) , relayOrder(relayOrder_)
, introset(introset_) , introset(introset_)
{ {
} }
bool bool
PublishServiceJob::Validate(const service::EncryptedIntroSet &value) const PublishServiceJob::Validate(const service::EncryptedIntroSet& value) const
{ {
if(value.derivedSigningKey != introset.derivedSigningKey) if (value.derivedSigningKey != introset.derivedSigningKey)
{ {
llarp::LogWarn( llarp::LogWarn("publish introset acknowledgement acked a different service");
"publish introset acknowledgement acked a different service");
return false; return false;
} }
const llarp_time_t now = llarp::time_now_ms(); const llarp_time_t now = llarp::time_now_ms();
@ -35,36 +36,35 @@ namespace llarp
} }
void void
PublishServiceJob::Start(const TXOwner &peer) PublishServiceJob::Start(const TXOwner& peer)
{ {
parent->DHTSendTo( parent->DHTSendTo(
peer.node.as_array(), peer.node.as_array(), new PublishIntroMessage(introset, peer.txid, false, relayOrder));
new PublishIntroMessage(introset, peer.txid, false, relayOrder));
} }
void void
PublishServiceJob::SendReply() PublishServiceJob::SendReply()
{ {
parent->DHTSendTo(whoasked.node.as_array(), parent->DHTSendTo(whoasked.node.as_array(), new GotIntroMessage({introset}, whoasked.txid));
new GotIntroMessage({introset}, whoasked.txid));
} }
LocalPublishServiceJob::LocalPublishServiceJob( LocalPublishServiceJob::LocalPublishServiceJob(
const TXOwner &peer, const PathID_t &fromID, uint64_t _txid, const TXOwner& peer,
const service::EncryptedIntroSet &introset, AbstractContext *ctx, const PathID_t& fromID,
uint64_t _txid,
const service::EncryptedIntroSet& introset,
AbstractContext* ctx,
uint64_t relayOrder) uint64_t relayOrder)
: PublishServiceJob(peer, introset, ctx, relayOrder) : PublishServiceJob(peer, introset, ctx, relayOrder), localPath(fromID), txid(_txid)
, localPath(fromID)
, txid(_txid)
{ {
} }
void void
LocalPublishServiceJob::SendReply() LocalPublishServiceJob::SendReply()
{ {
auto path = parent->GetRouter()->pathContext().GetByUpstream( auto path =
parent->OurKey().as_array(), localPath); parent->GetRouter()->pathContext().GetByUpstream(parent->OurKey().as_array(), localPath);
if(!path) if (!path)
{ {
llarp::LogWarn( llarp::LogWarn(
"did not send reply for relayed dht request, no such local path " "did not send reply for relayed dht request, no such local path "
@ -74,7 +74,7 @@ namespace llarp
} }
routing::DHTMessage msg; routing::DHTMessage msg;
msg.M.emplace_back(new GotIntroMessage({introset}, txid)); msg.M.emplace_back(new GotIntroMessage({introset}, txid));
if(!path->SendRoutingMessage(msg, parent->GetRouter())) if (!path->SendRoutingMessage(msg, parent->GetRouter()))
{ {
llarp::LogWarn( llarp::LogWarn(
"failed to send routing message when informing result of dht " "failed to send routing message when informing result of dht "

@ -12,20 +12,22 @@ namespace llarp
{ {
namespace dht namespace dht
{ {
struct PublishServiceJob : public TX< TXOwner, service::EncryptedIntroSet > struct PublishServiceJob : public TX<TXOwner, service::EncryptedIntroSet>
{ {
uint64_t relayOrder; uint64_t relayOrder;
service::EncryptedIntroSet introset; service::EncryptedIntroSet introset;
PublishServiceJob(const TXOwner &asker, PublishServiceJob(
const service::EncryptedIntroSet &introset, const TXOwner& asker,
AbstractContext *ctx, uint64_t relayOrder); const service::EncryptedIntroSet& introset,
AbstractContext* ctx,
uint64_t relayOrder);
bool bool
Validate(const service::EncryptedIntroSet &introset) const override; Validate(const service::EncryptedIntroSet& introset) const override;
void void
Start(const TXOwner &peer) override; Start(const TXOwner& peer) override;
virtual void virtual void
SendReply() override; SendReply() override;
@ -35,10 +37,13 @@ namespace llarp
{ {
PathID_t localPath; PathID_t localPath;
uint64_t txid; uint64_t txid;
LocalPublishServiceJob(const TXOwner &peer, const PathID_t &fromID, LocalPublishServiceJob(
uint64_t txid, const TXOwner& peer,
const service::EncryptedIntroSet &introset, const PathID_t& fromID,
AbstractContext *ctx, uint64_t relayOrder); uint64_t txid,
const service::EncryptedIntroSet& introset,
AbstractContext* ctx,
uint64_t relayOrder);
void void
SendReply() override; SendReply() override;

@ -13,21 +13,21 @@ namespace llarp
{ {
namespace dht namespace dht
{ {
RecursiveRouterLookup::RecursiveRouterLookup(const TXOwner &_whoasked, RecursiveRouterLookup::RecursiveRouterLookup(
const RouterID &_target, const TXOwner& _whoasked,
AbstractContext *ctx, const RouterID& _target,
RouterLookupHandler result) AbstractContext* ctx,
: TX< RouterID, RouterContact >(_whoasked, _target, ctx) RouterLookupHandler result)
, resultHandler(std::move(result)) : TX<RouterID, RouterContact>(_whoasked, _target, ctx), resultHandler(std::move(result))
{ {
peersAsked.insert(ctx->OurKey()); peersAsked.insert(ctx->OurKey());
} }
bool bool
RecursiveRouterLookup::Validate(const RouterContact &rc) const RecursiveRouterLookup::Validate(const RouterContact& rc) const
{ {
if(!rc.Verify(parent->Now())) if (!rc.Verify(parent->Now()))
{ {
llarp::LogWarn("rc from lookup result is invalid"); llarp::LogWarn("rc from lookup result is invalid");
return false; return false;
@ -36,36 +36,35 @@ namespace llarp
} }
void void
RecursiveRouterLookup::Start(const TXOwner &peer) RecursiveRouterLookup::Start(const TXOwner& peer)
{ {
parent->DHTSendTo(peer.node.as_array(), parent->DHTSendTo(peer.node.as_array(), new FindRouterMessage(peer.txid, target));
new FindRouterMessage(peer.txid, target));
} }
void void
RecursiveRouterLookup::SendReply() RecursiveRouterLookup::SendReply()
{ {
if(valuesFound.size()) if (valuesFound.size())
{ {
RouterContact found; RouterContact found;
for(const auto &rc : valuesFound) for (const auto& rc : valuesFound)
{ {
if(found.OtherIsNewer(rc) if (found.OtherIsNewer(rc) && parent->GetRouter()->rcLookupHandler().CheckRC(rc))
&& parent->GetRouter()->rcLookupHandler().CheckRC(rc))
found = rc; found = rc;
} }
valuesFound.clear(); valuesFound.clear();
valuesFound.emplace_back(found); valuesFound.emplace_back(found);
} }
if(resultHandler) if (resultHandler)
{ {
resultHandler(valuesFound); resultHandler(valuesFound);
} }
if(whoasked.node != parent->OurKey()) if (whoasked.node != parent->OurKey())
{ {
parent->DHTSendTo( parent->DHTSendTo(
whoasked.node.as_array(), whoasked.node.as_array(),
new GotRouterMessage({}, whoasked.txid, valuesFound, false), false); new GotRouterMessage({}, whoasked.txid, valuesFound, false),
false);
} }
} }
} // namespace dht } // namespace dht

@ -10,17 +10,20 @@ namespace llarp
{ {
namespace dht namespace dht
{ {
struct RecursiveRouterLookup : public TX< RouterID, RouterContact > struct RecursiveRouterLookup : public TX<RouterID, RouterContact>
{ {
RouterLookupHandler resultHandler; RouterLookupHandler resultHandler;
RecursiveRouterLookup(const TXOwner &whoasked, const RouterID &target, RecursiveRouterLookup(
AbstractContext *ctx, RouterLookupHandler result); const TXOwner& whoasked,
const RouterID& target,
AbstractContext* ctx,
RouterLookupHandler result);
bool bool
Validate(const RouterContact &rc) const override; Validate(const RouterContact& rc) const override;
void void
Start(const TXOwner &peer) override; Start(const TXOwner& peer) override;
void void
SendReply() override; SendReply() override;

@ -10,9 +10,12 @@ namespace llarp
namespace dht namespace dht
{ {
ServiceAddressLookup::ServiceAddressLookup( ServiceAddressLookup::ServiceAddressLookup(
const TXOwner &asker, const Key_t &addr, AbstractContext *ctx, const TXOwner& asker,
uint32_t order, service::EncryptedIntroSetLookupHandler handler) const Key_t& addr,
: TX< TXOwner, service::EncryptedIntroSet >(asker, asker, ctx) AbstractContext* ctx,
uint32_t order,
service::EncryptedIntroSetLookupHandler handler)
: TX<TXOwner, service::EncryptedIntroSet>(asker, asker, ctx)
, location(addr) , location(addr)
, handleResult(std::move(handler)) , handleResult(std::move(handler))
, relayOrder(order) , relayOrder(order)
@ -21,15 +24,14 @@ namespace llarp
} }
bool bool
ServiceAddressLookup::Validate( ServiceAddressLookup::Validate(const service::EncryptedIntroSet& value) const
const service::EncryptedIntroSet &value) const
{ {
if(!value.Verify(parent->Now())) if (!value.Verify(parent->Now()))
{ {
llarp::LogWarn("Got invalid introset from service lookup"); llarp::LogWarn("Got invalid introset from service lookup");
return false; return false;
} }
if(value.derivedSigningKey != location) if (value.derivedSigningKey != location)
{ {
llarp::LogWarn("got introset with wrong target from service lookup"); llarp::LogWarn("got introset with wrong target from service lookup");
return false; return false;
@ -38,33 +40,32 @@ namespace llarp
} }
void void
ServiceAddressLookup::Start(const TXOwner &peer) ServiceAddressLookup::Start(const TXOwner& peer)
{ {
parent->DHTSendTo(peer.node.as_array(), parent->DHTSendTo(
new FindIntroMessage(peer.txid, location, relayOrder)); peer.node.as_array(), new FindIntroMessage(peer.txid, location, relayOrder));
} }
void void
ServiceAddressLookup::SendReply() ServiceAddressLookup::SendReply()
{ {
// get newest introset // get newest introset
if(valuesFound.size()) if (valuesFound.size())
{ {
llarp::service::EncryptedIntroSet found; llarp::service::EncryptedIntroSet found;
for(const auto &introset : valuesFound) for (const auto& introset : valuesFound)
{ {
if(found.OtherIsNewer(introset)) if (found.OtherIsNewer(introset))
found = introset; found = introset;
} }
valuesFound.clear(); valuesFound.clear();
valuesFound.emplace_back(found); valuesFound.emplace_back(found);
} }
if(handleResult) if (handleResult)
{ {
handleResult(valuesFound); handleResult(valuesFound);
} }
parent->DHTSendTo(whoasked.node.as_array(), parent->DHTSendTo(whoasked.node.as_array(), new GotIntroMessage(valuesFound, whoasked.txid));
new GotIntroMessage(valuesFound, whoasked.txid));
} }
} // namespace dht } // namespace dht
} // namespace llarp } // namespace llarp

@ -12,22 +12,24 @@ namespace llarp
{ {
struct TXOwner; struct TXOwner;
struct ServiceAddressLookup struct ServiceAddressLookup : public TX<TXOwner, service::EncryptedIntroSet>
: public TX< TXOwner, service::EncryptedIntroSet >
{ {
Key_t location; Key_t location;
service::EncryptedIntroSetLookupHandler handleResult; service::EncryptedIntroSetLookupHandler handleResult;
uint32_t relayOrder; uint32_t relayOrder;
ServiceAddressLookup(const TXOwner &asker, const Key_t &addr, ServiceAddressLookup(
AbstractContext *ctx, uint32_t relayOrder, const TXOwner& asker,
service::EncryptedIntroSetLookupHandler handler); const Key_t& addr,
AbstractContext* ctx,
uint32_t relayOrder,
service::EncryptedIntroSetLookupHandler handler);
bool bool
Validate(const service::EncryptedIntroSet &value) const override; Validate(const service::EncryptedIntroSet& value) const override;
void void
Start(const TXOwner &peer) override; Start(const TXOwner& peer) override;
void void
SendReply() override; SendReply() override;

@ -8,16 +8,16 @@ namespace llarp
namespace dht namespace dht
{ {
bool bool
TagLookup::Validate(const service::EncryptedIntroSet &introset) const TagLookup::Validate(const service::EncryptedIntroSet& introset) const
{ {
if(!introset.Verify(parent->Now())) if (!introset.Verify(parent->Now()))
{ {
llarp::LogWarn("got invalid introset from tag lookup"); llarp::LogWarn("got invalid introset from tag lookup");
return false; return false;
} }
if(not introset.topic.has_value()) if (not introset.topic.has_value())
return false; return false;
if(introset.topic.value() != target) if (introset.topic.value() != target)
{ {
llarp::LogWarn("got introset with missmatched topic in tag lookup"); llarp::LogWarn("got introset with missmatched topic in tag lookup");
return false; return false;
@ -26,17 +26,15 @@ namespace llarp
} }
void void
TagLookup::Start(const TXOwner &peer) TagLookup::Start(const TXOwner& peer)
{ {
parent->DHTSendTo(peer.node.as_array(), parent->DHTSendTo(peer.node.as_array(), new FindIntroMessage(target, peer.txid));
new FindIntroMessage(target, peer.txid));
} }
void void
TagLookup::SendReply() TagLookup::SendReply()
{ {
parent->DHTSendTo(whoasked.node.as_array(), parent->DHTSendTo(whoasked.node.as_array(), new GotIntroMessage({}, whoasked.txid));
new GotIntroMessage({}, whoasked.txid));
} }
} // namespace dht } // namespace dht
} // namespace llarp } // namespace llarp

@ -9,21 +9,20 @@ namespace llarp
{ {
namespace dht namespace dht
{ {
struct TagLookup : public TX< service::Tag, service::EncryptedIntroSet > struct TagLookup : public TX<service::Tag, service::EncryptedIntroSet>
{ {
uint64_t recursionDepth; uint64_t recursionDepth;
TagLookup(const TXOwner &asker, const service::Tag &tag, TagLookup(
AbstractContext *ctx, uint64_t recursion) const TXOwner& asker, const service::Tag& tag, AbstractContext* ctx, uint64_t recursion)
: TX< service::Tag, service::EncryptedIntroSet >(asker, tag, ctx) : TX<service::Tag, service::EncryptedIntroSet>(asker, tag, ctx), recursionDepth(recursion)
, recursionDepth(recursion)
{ {
} }
bool bool
Validate(const service::EncryptedIntroSet &introset) const override; Validate(const service::EncryptedIntroSet& introset) const override;
void void
Start(const TXOwner &peer) override; Start(const TXOwner& peer) override;
void void
SendReply() override; SendReply() override;

@ -15,13 +15,13 @@ namespace llarp
{ {
struct AbstractContext; struct AbstractContext;
template < typename K, typename V > template <typename K, typename V>
struct TX struct TX
{ {
K target; K target;
AbstractContext* parent; AbstractContext* parent;
std::set< Key_t > peersAsked; std::set<Key_t> peersAsked;
std::vector< V > valuesFound; std::vector<V> valuesFound;
TXOwner whoasked; TXOwner whoasked;
TX(const TXOwner& asker, const K& k, AbstractContext* p) TX(const TXOwner& asker, const K& k, AbstractContext* p)
@ -39,17 +39,19 @@ namespace llarp
{ {
util::StatusObject obj{{"whoasked", whoasked.ExtractStatus()}, util::StatusObject obj{{"whoasked", whoasked.ExtractStatus()},
{"target", target.ExtractStatus()}}; {"target", target.ExtractStatus()}};
std::vector< util::StatusObject > foundObjs; std::vector<util::StatusObject> foundObjs;
std::transform(valuesFound.begin(), valuesFound.end(), std::transform(
std::back_inserter(foundObjs), valuesFound.begin(),
[](const auto& item) -> util::StatusObject { valuesFound.end(),
return item.ExtractStatus(); std::back_inserter(foundObjs),
}); [](const auto& item) -> util::StatusObject { return item.ExtractStatus(); });
obj["found"] = foundObjs; obj["found"] = foundObjs;
std::vector< std::string > asked; std::vector<std::string> asked;
std::transform( std::transform(
peersAsked.begin(), peersAsked.end(), std::back_inserter(asked), peersAsked.begin(),
peersAsked.end(),
std::back_inserter(asked),
[](const auto& item) -> std::string { return item.ToString(); }); [](const auto& item) -> std::string { return item.ToString(); });
obj["asked"] = asked; obj["asked"] = asked;
return obj; return obj;
@ -65,12 +67,12 @@ namespace llarp
SendReply() = 0; SendReply() = 0;
}; };
template < typename K, typename V > template <typename K, typename V>
inline void inline void
TX< K, V >::OnFound(const Key_t& askedPeer, const V& value) TX<K, V>::OnFound(const Key_t& askedPeer, const V& value)
{ {
peersAsked.insert(askedPeer); peersAsked.insert(askedPeer);
if(Validate(value)) if (Validate(value))
{ {
valuesFound.push_back(value); valuesFound.push_back(value);
} }

@ -13,46 +13,51 @@ namespace llarp
{ {
namespace dht namespace dht
{ {
template < typename K, typename V, typename K_Hash > template <typename K, typename V, typename K_Hash>
struct TXHolder struct TXHolder
{ {
using TXPtr = std::unique_ptr< TX< K, V > >; using TXPtr = std::unique_ptr<TX<K, V>>;
// tx who are waiting for a reply for each key // tx who are waiting for a reply for each key
std::unordered_multimap< K, TXOwner, K_Hash > waiting; std::unordered_multimap<K, TXOwner, K_Hash> waiting;
// tx timesouts by key // tx timesouts by key
std::unordered_map< K, llarp_time_t, K_Hash > timeouts; std::unordered_map<K, llarp_time_t, K_Hash> timeouts;
// maps remote peer with tx to handle reply from them // maps remote peer with tx to handle reply from them
std::unordered_map< TXOwner, TXPtr, TXOwner::Hash > tx; std::unordered_map<TXOwner, TXPtr, TXOwner::Hash> tx;
const TX< K, V >* const TX<K, V>*
GetPendingLookupFrom(const TXOwner& owner) const; GetPendingLookupFrom(const TXOwner& owner) const;
util::StatusObject util::StatusObject
ExtractStatus() const ExtractStatus() const
{ {
util::StatusObject obj{}; util::StatusObject obj{};
std::vector< util::StatusObject > txObjs, timeoutsObjs, waitingObjs; std::vector<util::StatusObject> txObjs, timeoutsObjs, waitingObjs;
std::transform(tx.begin(), tx.end(), std::back_inserter(txObjs), std::transform(
[](const auto& item) -> util::StatusObject { tx.begin(),
return util::StatusObject{ tx.end(),
{"owner", item.first.ExtractStatus()}, std::back_inserter(txObjs),
{"tx", item.second->ExtractStatus()}}; [](const auto& item) -> util::StatusObject {
}); return util::StatusObject{{"owner", item.first.ExtractStatus()},
{"tx", item.second->ExtractStatus()}};
});
obj["tx"] = txObjs; obj["tx"] = txObjs;
std::transform( std::transform(
timeouts.begin(), timeouts.end(), std::back_inserter(timeoutsObjs), timeouts.begin(),
timeouts.end(),
std::back_inserter(timeoutsObjs),
[](const auto& item) -> util::StatusObject { [](const auto& item) -> util::StatusObject {
return util::StatusObject{{"time", to_json(item.second)}, return util::StatusObject{{"time", to_json(item.second)},
{"target", item.first.ExtractStatus()}}; {"target", item.first.ExtractStatus()}};
}); });
obj["timeouts"] = timeoutsObjs; obj["timeouts"] = timeoutsObjs;
std::transform(waiting.begin(), waiting.end(), std::transform(
std::back_inserter(waitingObjs), waiting.begin(),
[](const auto& item) -> util::StatusObject { waiting.end(),
return util::StatusObject{ std::back_inserter(waitingObjs),
{"target", item.first.ExtractStatus()}, [](const auto& item) -> util::StatusObject {
{"whoasked", item.second.ExtractStatus()}}; return util::StatusObject{{"target", item.first.ExtractStatus()},
}); {"whoasked", item.second.ExtractStatus()}};
});
obj["waiting"] = waitingObjs; obj["waiting"] = waitingObjs;
return obj; return obj;
} }
@ -70,34 +75,42 @@ namespace llarp
} }
void void
NewTX(const TXOwner& askpeer, const TXOwner& whoasked, const K& k, NewTX(
TX< K, V >* t, llarp_time_t requestTimeoutMS = 15s); const TXOwner& askpeer,
const TXOwner& whoasked,
const K& k,
TX<K, V>* t,
llarp_time_t requestTimeoutMS = 15s);
/// mark tx as not fond /// mark tx as not fond
void void
NotFound(const TXOwner& from, const std::unique_ptr< Key_t >& next); NotFound(const TXOwner& from, const std::unique_ptr<Key_t>& next);
void void
Found(const TXOwner& from, const K& k, const std::vector< V >& values) Found(const TXOwner& from, const K& k, const std::vector<V>& values)
{ {
Inform(from, k, values, true); Inform(from, k, values, true);
} }
/// inform all watches for key of values found /// inform all watches for key of values found
void void
Inform(TXOwner from, K key, std::vector< V > values, Inform(
bool sendreply = false, bool removeTimeouts = true); TXOwner from,
K key,
std::vector<V> values,
bool sendreply = false,
bool removeTimeouts = true);
void void
Expire(llarp_time_t now); Expire(llarp_time_t now);
}; };
template < typename K, typename V, typename K_Hash > template <typename K, typename V, typename K_Hash>
const TX< K, V >* const TX<K, V>*
TXHolder< K, V, K_Hash >::GetPendingLookupFrom(const TXOwner& owner) const TXHolder<K, V, K_Hash>::GetPendingLookupFrom(const TXOwner& owner) const
{ {
auto itr = tx.find(owner); auto itr = tx.find(owner);
if(itr == tx.end()) if (itr == tx.end())
{ {
return nullptr; return nullptr;
} }
@ -105,60 +118,60 @@ namespace llarp
return itr->second.get(); return itr->second.get();
} }
template < typename K, typename V, typename K_Hash > template <typename K, typename V, typename K_Hash>
void void
TXHolder< K, V, K_Hash >::NewTX(const TXOwner& askpeer, TXHolder<K, V, K_Hash>::NewTX(
const TXOwner& whoasked, const K& k, const TXOwner& askpeer,
TX< K, V >* t, const TXOwner& whoasked,
llarp_time_t requestTimeoutMS) const K& k,
TX<K, V>* t,
llarp_time_t requestTimeoutMS)
{ {
(void)whoasked; (void)whoasked;
tx.emplace(askpeer, std::unique_ptr< TX< K, V > >(t)); tx.emplace(askpeer, std::unique_ptr<TX<K, V>>(t));
auto count = waiting.count(k); auto count = waiting.count(k);
waiting.emplace(k, askpeer); waiting.emplace(k, askpeer);
auto itr = timeouts.find(k); auto itr = timeouts.find(k);
if(itr == timeouts.end()) if (itr == timeouts.end())
{ {
timeouts.emplace(k, time_now_ms() + requestTimeoutMS); timeouts.emplace(k, time_now_ms() + requestTimeoutMS);
} }
if(count == 0) if (count == 0)
{ {
t->Start(askpeer); t->Start(askpeer);
} }
} }
template < typename K, typename V, typename K_Hash > template <typename K, typename V, typename K_Hash>
void void
TXHolder< K, V, K_Hash >::NotFound(const TXOwner& from, TXHolder<K, V, K_Hash>::NotFound(const TXOwner& from, const std::unique_ptr<Key_t>&)
const std::unique_ptr< Key_t >&)
{ {
auto txitr = tx.find(from); auto txitr = tx.find(from);
if(txitr == tx.end()) if (txitr == tx.end())
{ {
return; return;
} }
Inform(from, txitr->second->target, {}, true, true); Inform(from, txitr->second->target, {}, true, true);
} }
template < typename K, typename V, typename K_Hash > template <typename K, typename V, typename K_Hash>
void void
TXHolder< K, V, K_Hash >::Inform(TXOwner from, K key, TXHolder<K, V, K_Hash>::Inform(
std::vector< V > values, bool sendreply, TXOwner from, K key, std::vector<V> values, bool sendreply, bool removeTimeouts)
bool removeTimeouts)
{ {
auto range = waiting.equal_range(key); auto range = waiting.equal_range(key);
auto itr = range.first; auto itr = range.first;
while(itr != range.second) while (itr != range.second)
{ {
auto txitr = tx.find(itr->second); auto txitr = tx.find(itr->second);
if(txitr != tx.end()) if (txitr != tx.end())
{ {
for(const auto& value : values) for (const auto& value : values)
{ {
txitr->second->OnFound(from.node, value); txitr->second->OnFound(from.node, value);
} }
if(sendreply) if (sendreply)
{ {
txitr->second->SendReply(); txitr->second->SendReply();
tx.erase(txitr); tx.erase(txitr);
@ -167,25 +180,25 @@ namespace llarp
++itr; ++itr;
} }
if(sendreply) if (sendreply)
{ {
waiting.erase(key); waiting.erase(key);
} }
if(removeTimeouts) if (removeTimeouts)
{ {
timeouts.erase(key); timeouts.erase(key);
} }
} }
template < typename K, typename V, typename K_Hash > template <typename K, typename V, typename K_Hash>
void void
TXHolder< K, V, K_Hash >::Expire(llarp_time_t now) TXHolder<K, V, K_Hash>::Expire(llarp_time_t now)
{ {
auto itr = timeouts.begin(); auto itr = timeouts.begin();
while(itr != timeouts.end()) while (itr != timeouts.end())
{ {
if(now >= itr->second) if (now >= itr->second)
{ {
Inform(TXOwner{}, itr->first, {}, true, false); Inform(TXOwner{}, itr->first, {}, true, false);
itr = timeouts.erase(itr); itr = timeouts.erase(itr);

@ -14,9 +14,9 @@ namespace llarp
Key_t node; Key_t node;
uint64_t txid = 0; uint64_t txid = 0;
TXOwner() = default; TXOwner() = default;
TXOwner(const TXOwner&) = default; TXOwner(const TXOwner&) = default;
TXOwner(TXOwner&&) = default; TXOwner(TXOwner&&) = default;
TXOwner& TXOwner&
operator=(const TXOwner&) = default; operator=(const TXOwner&) = default;

@ -7,24 +7,24 @@ namespace llarp
{ {
namespace dns namespace dns
{ {
constexpr uint16_t qTypeAAAA = 28; constexpr uint16_t qTypeAAAA = 28;
constexpr uint16_t qTypeTXT = 16; constexpr uint16_t qTypeTXT = 16;
constexpr uint16_t qTypeMX = 15; constexpr uint16_t qTypeMX = 15;
constexpr uint16_t qTypePTR = 12; constexpr uint16_t qTypePTR = 12;
constexpr uint16_t qTypeCNAME = 5; constexpr uint16_t qTypeCNAME = 5;
constexpr uint16_t qTypeNS = 2; constexpr uint16_t qTypeNS = 2;
constexpr uint16_t qTypeA = 1; constexpr uint16_t qTypeA = 1;
constexpr uint16_t qClassIN = 1; constexpr uint16_t qClassIN = 1;
constexpr uint16_t flags_QR = (1 << 15); constexpr uint16_t flags_QR = (1 << 15);
constexpr uint16_t flags_AA = (1 << 10); constexpr uint16_t flags_AA = (1 << 10);
constexpr uint16_t flags_TC = (1 << 9); constexpr uint16_t flags_TC = (1 << 9);
constexpr uint16_t flags_RD = (1 << 8); constexpr uint16_t flags_RD = (1 << 8);
constexpr uint16_t flags_RA = (1 << 7); constexpr uint16_t flags_RA = (1 << 7);
constexpr uint16_t flags_RCODENameError = (3); constexpr uint16_t flags_RCODENameError = (3);
constexpr uint16_t flags_RCODEServFail = (2); constexpr uint16_t flags_RCODEServFail = (2);
constexpr uint16_t flags_RCODENoError = (0); constexpr uint16_t flags_RCODENoError = (0);
} // namespace dns } // namespace dns
} // namespace llarp } // namespace llarp

@ -16,15 +16,15 @@ namespace llarp
bool bool
MessageHeader::Encode(llarp_buffer_t* buf) const MessageHeader::Encode(llarp_buffer_t* buf) const
{ {
if(!buf->put_uint16(id)) if (!buf->put_uint16(id))
return false; return false;
if(!buf->put_uint16(fields)) if (!buf->put_uint16(fields))
return false; return false;
if(!buf->put_uint16(qd_count)) if (!buf->put_uint16(qd_count))
return false; return false;
if(!buf->put_uint16(an_count)) if (!buf->put_uint16(an_count))
return false; return false;
if(!buf->put_uint16(ns_count)) if (!buf->put_uint16(ns_count))
return false; return false;
return buf->put_uint16(ar_count); return buf->put_uint16(ar_count);
} }
@ -32,17 +32,17 @@ namespace llarp
bool bool
MessageHeader::Decode(llarp_buffer_t* buf) MessageHeader::Decode(llarp_buffer_t* buf)
{ {
if(!buf->read_uint16(id)) if (!buf->read_uint16(id))
return false; return false;
if(!buf->read_uint16(fields)) if (!buf->read_uint16(fields))
return false; return false;
if(!buf->read_uint16(qd_count)) if (!buf->read_uint16(qd_count))
return false; return false;
if(!buf->read_uint16(an_count)) if (!buf->read_uint16(an_count))
return false; return false;
if(!buf->read_uint16(ns_count)) if (!buf->read_uint16(ns_count))
return false; return false;
if(!buf->read_uint16(ar_count)) if (!buf->read_uint16(ar_count))
return false; return false;
return true; return true;
} }
@ -67,8 +67,7 @@ namespace llarp
{ {
} }
Message::Message(const MessageHeader& hdr) Message::Message(const MessageHeader& hdr) : hdr_id(hdr.id), hdr_fields(hdr.fields)
: hdr_id(hdr.id), hdr_fields(hdr.fields)
{ {
questions.resize(size_t(hdr.qd_count)); questions.resize(size_t(hdr.qd_count));
answers.resize(size_t(hdr.an_count)); answers.resize(size_t(hdr.an_count));
@ -80,22 +79,22 @@ namespace llarp
Message::Encode(llarp_buffer_t* buf) const Message::Encode(llarp_buffer_t* buf) const
{ {
MessageHeader hdr; MessageHeader hdr;
hdr.id = hdr_id; hdr.id = hdr_id;
hdr.fields = hdr_fields; hdr.fields = hdr_fields;
hdr.qd_count = questions.size(); hdr.qd_count = questions.size();
hdr.an_count = answers.size(); hdr.an_count = answers.size();
hdr.ns_count = 0; hdr.ns_count = 0;
hdr.ar_count = 0; hdr.ar_count = 0;
if(!hdr.Encode(buf)) if (!hdr.Encode(buf))
return false; return false;
for(const auto& question : questions) for (const auto& question : questions)
if(!question.Encode(buf)) if (!question.Encode(buf))
return false; return false;
for(const auto& answer : answers) for (const auto& answer : answers)
if(!answer.Encode(buf)) if (!answer.Encode(buf))
return false; return false;
return true; return true;
@ -104,18 +103,18 @@ namespace llarp
bool bool
Message::Decode(llarp_buffer_t* buf) Message::Decode(llarp_buffer_t* buf)
{ {
for(auto& qd : questions) for (auto& qd : questions)
{ {
if(!qd.Decode(buf)) if (!qd.Decode(buf))
{ {
llarp::LogError("failed to decode question"); llarp::LogError("failed to decode question");
return false; return false;
} }
llarp::LogDebug(qd); llarp::LogDebug(qd);
} }
for(auto& an : answers) for (auto& an : answers)
{ {
if(not an.Decode(buf)) if (not an.Decode(buf))
{ {
llarp::LogDebug("failed to decode answer"); llarp::LogDebug("failed to decode answer");
return false; return false;
@ -126,7 +125,7 @@ namespace llarp
void Message::AddServFail(RR_TTL_t) void Message::AddServFail(RR_TTL_t)
{ {
if(questions.size()) if (questions.size())
{ {
hdr_fields |= flags_RCODEServFail; hdr_fields |= flags_RCODEServFail;
// authorative response with recursion available // authorative response with recursion available
@ -145,14 +144,14 @@ namespace llarp
void void
Message::AddINReply(llarp::huint128_t ip, bool isV6, RR_TTL_t ttl) Message::AddINReply(llarp::huint128_t ip, bool isV6, RR_TTL_t ttl)
{ {
if(questions.size()) if (questions.size())
{ {
hdr_fields = reply_flags(hdr_fields); hdr_fields = reply_flags(hdr_fields);
ResourceRecord rec; ResourceRecord rec;
rec.rr_name = questions[0].qname; rec.rr_name = questions[0].qname;
rec.rr_class = qClassIN; rec.rr_class = qClassIN;
rec.ttl = ttl; rec.ttl = ttl;
if(isV6) if (isV6)
{ {
rec.rr_type = qTypeAAAA; rec.rr_type = qTypeAAAA;
ip.ToV6(rec.rData); ip.ToV6(rec.rData);
@ -160,7 +159,7 @@ namespace llarp
else else
{ {
const auto addr = net::IPPacket::TruncateV6(ip); const auto addr = net::IPPacket::TruncateV6(ip);
rec.rr_type = qTypeA; rec.rr_type = qTypeA;
rec.rData.resize(4); rec.rData.resize(4);
htobe32buf(rec.rData.data(), addr.h); htobe32buf(rec.rData.data(), addr.h);
} }
@ -171,20 +170,20 @@ namespace llarp
void void
Message::AddAReply(std::string name, RR_TTL_t ttl) Message::AddAReply(std::string name, RR_TTL_t ttl)
{ {
if(questions.size()) if (questions.size())
{ {
hdr_fields = reply_flags(hdr_fields); hdr_fields = reply_flags(hdr_fields);
const auto& question = questions[0]; const auto& question = questions[0];
answers.emplace_back(); answers.emplace_back();
auto& rec = answers.back(); auto& rec = answers.back();
rec.rr_name = question.qname; rec.rr_name = question.qname;
rec.rr_type = question.qtype; rec.rr_type = question.qtype;
rec.rr_class = qClassIN; rec.rr_class = qClassIN;
rec.ttl = ttl; rec.ttl = ttl;
std::array< byte_t, 512 > tmp = {{0}}; std::array<byte_t, 512> tmp = {{0}};
llarp_buffer_t buf(tmp); llarp_buffer_t buf(tmp);
if(EncodeName(&buf, name)) if (EncodeName(&buf, name))
{ {
buf.sz = buf.cur - buf.base; buf.sz = buf.cur - buf.base;
rec.rData.resize(buf.sz); rec.rData.resize(buf.sz);
@ -196,20 +195,20 @@ namespace llarp
void void
Message::AddNSReply(std::string name, RR_TTL_t ttl) Message::AddNSReply(std::string name, RR_TTL_t ttl)
{ {
if(not questions.empty()) if (not questions.empty())
{ {
hdr_fields = reply_flags(hdr_fields); hdr_fields = reply_flags(hdr_fields);
const auto& question = questions[0]; const auto& question = questions[0];
answers.emplace_back(); answers.emplace_back();
auto& rec = answers.back(); auto& rec = answers.back();
rec.rr_name = question.qname; rec.rr_name = question.qname;
rec.rr_type = qTypeNS; rec.rr_type = qTypeNS;
rec.rr_class = qClassIN; rec.rr_class = qClassIN;
rec.ttl = ttl; rec.ttl = ttl;
std::array< byte_t, 512 > tmp = {{0}}; std::array<byte_t, 512> tmp = {{0}};
llarp_buffer_t buf(tmp); llarp_buffer_t buf(tmp);
if(EncodeName(&buf, name)) if (EncodeName(&buf, name))
{ {
buf.sz = buf.cur - buf.base; buf.sz = buf.cur - buf.base;
rec.rData.resize(buf.sz); rec.rData.resize(buf.sz);
@ -221,20 +220,20 @@ namespace llarp
void void
Message::AddCNAMEReply(std::string name, RR_TTL_t ttl) Message::AddCNAMEReply(std::string name, RR_TTL_t ttl)
{ {
if(questions.size()) if (questions.size())
{ {
hdr_fields = reply_flags(hdr_fields); hdr_fields = reply_flags(hdr_fields);
const auto& question = questions[0]; const auto& question = questions[0];
answers.emplace_back(); answers.emplace_back();
auto& rec = answers.back(); auto& rec = answers.back();
rec.rr_name = question.qname; rec.rr_name = question.qname;
rec.rr_type = qTypeCNAME; rec.rr_type = qTypeCNAME;
rec.rr_class = qClassIN; rec.rr_class = qClassIN;
rec.ttl = ttl; rec.ttl = ttl;
std::array< byte_t, 512 > tmp = {{0}}; std::array<byte_t, 512> tmp = {{0}};
llarp_buffer_t buf(tmp); llarp_buffer_t buf(tmp);
if(EncodeName(&buf, name)) if (EncodeName(&buf, name))
{ {
buf.sz = buf.cur - buf.base; buf.sz = buf.cur - buf.base;
rec.rData.resize(buf.sz); rec.rData.resize(buf.sz);
@ -246,21 +245,21 @@ namespace llarp
void void
Message::AddMXReply(std::string name, uint16_t priority, RR_TTL_t ttl) Message::AddMXReply(std::string name, uint16_t priority, RR_TTL_t ttl)
{ {
if(questions.size()) if (questions.size())
{ {
hdr_fields = reply_flags(hdr_fields); hdr_fields = reply_flags(hdr_fields);
const auto& question = questions[0]; const auto& question = questions[0];
answers.emplace_back(); answers.emplace_back();
auto& rec = answers.back(); auto& rec = answers.back();
rec.rr_name = question.qname; rec.rr_name = question.qname;
rec.rr_type = qTypeMX; rec.rr_type = qTypeMX;
rec.rr_class = qClassIN; rec.rr_class = qClassIN;
rec.ttl = ttl; rec.ttl = ttl;
std::array< byte_t, 512 > tmp = {{0}}; std::array<byte_t, 512> tmp = {{0}};
llarp_buffer_t buf(tmp); llarp_buffer_t buf(tmp);
buf.put_uint16(priority); buf.put_uint16(priority);
if(EncodeName(&buf, name)) if (EncodeName(&buf, name))
{ {
buf.sz = buf.cur - buf.base; buf.sz = buf.cur - buf.base;
rec.rData.resize(buf.sz); rec.rData.resize(buf.sz);
@ -271,7 +270,7 @@ namespace llarp
void Message::AddNXReply(RR_TTL_t) void Message::AddNXReply(RR_TTL_t)
{ {
if(questions.size()) if (questions.size())
{ {
// authorative response with recursion available // authorative response with recursion available
hdr_fields = reply_flags(hdr_fields); hdr_fields = reply_flags(hdr_fields);

@ -9,9 +9,9 @@ namespace llarp
{ {
namespace dns namespace dns
{ {
using MsgID_t = uint16_t; using MsgID_t = uint16_t;
using Fields_t = uint16_t; using Fields_t = uint16_t;
using Count_t = uint16_t; using Count_t = uint16_t;
struct MessageHeader : public Serialize struct MessageHeader : public Serialize
{ {
@ -35,9 +35,9 @@ namespace llarp
bool bool
operator==(const MessageHeader& other) const operator==(const MessageHeader& other) const
{ {
return id == other.id && fields == other.fields return id == other.id && fields == other.fields && qd_count == other.qd_count
&& qd_count == other.qd_count && an_count == other.an_count && an_count == other.an_count && ns_count == other.ns_count
&& ns_count == other.ns_count && ar_count == other.ar_count; && ar_count == other.ar_count;
} }
}; };
@ -83,10 +83,10 @@ namespace llarp
MsgID_t hdr_id; MsgID_t hdr_id;
Fields_t hdr_fields; Fields_t hdr_fields;
std::vector< Question > questions; std::vector<Question> questions;
std::vector< ResourceRecord > answers; std::vector<ResourceRecord> answers;
std::vector< ResourceRecord > authorities; std::vector<ResourceRecord> authorities;
std::vector< ResourceRecord > additional; std::vector<ResourceRecord> additional;
}; };
inline std::ostream& inline std::ostream&

@ -13,7 +13,7 @@ namespace llarp
bool bool
DecodeName(llarp_buffer_t* buf, Name_t& name, bool trimTrailingDot) DecodeName(llarp_buffer_t* buf, Name_t& name, bool trimTrailingDot)
{ {
if(buf->size_left() < 1) if (buf->size_left() < 1)
return false; return false;
std::stringstream ss; std::stringstream ss;
size_t l; size_t l;
@ -21,19 +21,19 @@ namespace llarp
{ {
l = *buf->cur; l = *buf->cur;
buf->cur++; buf->cur++;
if(l) if (l)
{ {
if(buf->size_left() < l) if (buf->size_left() < l)
return false; return false;
ss << Name_t((const char*)buf->cur, l); ss << Name_t((const char*)buf->cur, l);
ss << "."; ss << ".";
} }
buf->cur = buf->cur + l; buf->cur = buf->cur + l;
} while(l); } while (l);
name = ss.str(); name = ss.str();
/// trim off last dot /// trim off last dot
if(trimTrailingDot) if (trimTrailingDot)
name = name.substr(0, name.find_last_of('.')); name = name.substr(0, name.find_last_of('.'));
return true; return true;
} }
@ -42,22 +42,22 @@ namespace llarp
EncodeName(llarp_buffer_t* buf, const Name_t& name) EncodeName(llarp_buffer_t* buf, const Name_t& name)
{ {
std::stringstream ss; std::stringstream ss;
if(name.size() && name[name.size() - 1] == '.') if (name.size() && name[name.size() - 1] == '.')
ss << name.substr(0, name.size() - 1); ss << name.substr(0, name.size() - 1);
else else
ss << name; ss << name;
std::string part; std::string part;
while(std::getline(ss, part, '.')) while (std::getline(ss, part, '.'))
{ {
size_t l = part.length(); size_t l = part.length();
if(l > 63) if (l > 63)
return false; return false;
*(buf->cur) = l; *(buf->cur) = l;
buf->cur++; buf->cur++;
if(buf->size_left() < l) if (buf->size_left() < l)
return false; return false;
if(l) if (l)
{ {
memcpy(buf->cur, part.data(), l); memcpy(buf->cur, part.data(), l);
buf->cur += l; buf->cur += l;
@ -74,46 +74,46 @@ namespace llarp
DecodePTR(const Name_t& name, huint128_t& ip) DecodePTR(const Name_t& name, huint128_t& ip)
{ {
bool isV6 = false; bool isV6 = false;
auto pos = name.find(".in-addr.arpa"); auto pos = name.find(".in-addr.arpa");
if(pos == std::string::npos) if (pos == std::string::npos)
{ {
pos = name.find(".ip6.arpa"); pos = name.find(".ip6.arpa");
isV6 = true; isV6 = true;
} }
if(pos == std::string::npos) if (pos == std::string::npos)
return false; return false;
std::string sub = name.substr(0, pos + 1); std::string sub = name.substr(0, pos + 1);
const auto numdots = std::count(sub.begin(), sub.end(), '.'); const auto numdots = std::count(sub.begin(), sub.end(), '.');
if(numdots == 4 && !isV6) if (numdots == 4 && !isV6)
{ {
uint8_t a, b, c, d; uint8_t a, b, c, d;
pos = sub.find('.'); pos = sub.find('.');
d = atoi(sub.substr(0, pos).c_str()); d = atoi(sub.substr(0, pos).c_str());
sub = sub.substr(pos + 1); sub = sub.substr(pos + 1);
pos = sub.find('.'); pos = sub.find('.');
c = atoi(sub.substr(0, pos).c_str()); c = atoi(sub.substr(0, pos).c_str());
sub = sub.substr(pos + 1); sub = sub.substr(pos + 1);
pos = sub.find('.'); pos = sub.find('.');
b = atoi(sub.substr(0, pos).c_str()); b = atoi(sub.substr(0, pos).c_str());
sub = sub.substr(pos + 1); sub = sub.substr(pos + 1);
pos = sub.find('.'); pos = sub.find('.');
a = atoi(sub.substr(0, pos).c_str()); a = atoi(sub.substr(0, pos).c_str());
ip = net::IPPacket::ExpandV4(llarp::ipaddr_ipv4_bits(a, b, c, d)); ip = net::IPPacket::ExpandV4(llarp::ipaddr_ipv4_bits(a, b, c, d));
return true; return true;
} }
if(numdots == 32 && isV6) if (numdots == 32 && isV6)
{ {
size_t idx = 0; size_t idx = 0;
uint8_t lo, hi; uint8_t lo, hi;
auto* ptr = (uint8_t*)&ip.h; auto* ptr = (uint8_t*)&ip.h;
while(idx < 16) while (idx < 16)
{ {
pos = sub.find('.'); pos = sub.find('.');
lo = (*sub.substr(0, pos).c_str()) - 'a'; lo = (*sub.substr(0, pos).c_str()) - 'a';
sub = sub.substr(pos + 1); sub = sub.substr(pos + 1);
pos = sub.find('.'); pos = sub.find('.');
hi = (*sub.substr(0, pos).c_str()) - 'a'; hi = (*sub.substr(0, pos).c_str()) - 'a';
sub = sub.substr(pos + 1); sub = sub.substr(pos + 1);
ptr[idx] = lo | (hi << 4); ptr[idx] = lo | (hi << 4);
++idx; ++idx;
} }

@ -21,9 +21,9 @@ namespace llarp
bool bool
Question::Encode(llarp_buffer_t* buf) const Question::Encode(llarp_buffer_t* buf) const
{ {
if(!EncodeName(buf, qname)) if (!EncodeName(buf, qname))
return false; return false;
if(!buf->put_uint16(qtype)) if (!buf->put_uint16(qtype))
return false; return false;
return buf->put_uint16(qclass); return buf->put_uint16(qclass);
} }
@ -31,17 +31,17 @@ namespace llarp
bool bool
Question::Decode(llarp_buffer_t* buf) Question::Decode(llarp_buffer_t* buf)
{ {
if(!DecodeName(buf, qname)) if (!DecodeName(buf, qname))
{ {
llarp::LogError("failed to decode name"); llarp::LogError("failed to decode name");
return false; return false;
} }
if(!buf->read_uint16(qtype)) if (!buf->read_uint16(qtype))
{ {
llarp::LogError("failed to decode type"); llarp::LogError("failed to decode type");
return false; return false;
} }
if(!buf->read_uint16(qclass)) if (!buf->read_uint16(qclass))
{ {
llarp::LogError("failed to decode class"); llarp::LogError("failed to decode class");
return false; return false;
@ -53,7 +53,7 @@ namespace llarp
Question::IsName(const std::string& other) const Question::IsName(const std::string& other) const
{ {
// does other have a . at the end? // does other have a . at the end?
if(other.find_last_of('.') == (other.size() - 1)) if (other.find_last_of('.') == (other.size() - 1))
return other == qname; return other == qname;
// no, add it and retry // no, add it and retry
return IsName(other + "."); return IsName(other + ".");

@ -9,7 +9,7 @@ namespace llarp
{ {
namespace dns namespace dns
{ {
using QType_t = uint16_t; using QType_t = uint16_t;
using QClass_t = uint16_t; using QClass_t = uint16_t;
struct Question : public Serialize struct Question : public Serialize
@ -29,8 +29,7 @@ namespace llarp
bool bool
operator==(const Question& other) const operator==(const Question& other) const
{ {
return qname == other.qname && qtype == other.qtype return qname == other.qname && qtype == other.qtype && qclass == other.qclass;
&& qclass == other.qclass;
} }
Name_t qname; Name_t qname;

@ -29,21 +29,21 @@ namespace llarp
bool bool
ResourceRecord::Encode(llarp_buffer_t* buf) const ResourceRecord::Encode(llarp_buffer_t* buf) const
{ {
if(not EncodeName(buf, rr_name)) if (not EncodeName(buf, rr_name))
return false; return false;
if(!buf->put_uint16(rr_type)) if (!buf->put_uint16(rr_type))
{ {
return false; return false;
} }
if(!buf->put_uint16(rr_class)) if (!buf->put_uint16(rr_class))
{ {
return false; return false;
} }
if(!buf->put_uint32(ttl)) if (!buf->put_uint32(ttl))
{ {
return false; return false;
} }
if(!EncodeRData(buf, rData)) if (!EncodeRData(buf, rData))
{ {
return false; return false;
} }
@ -54,24 +54,24 @@ namespace llarp
ResourceRecord::Decode(llarp_buffer_t* buf) ResourceRecord::Decode(llarp_buffer_t* buf)
{ {
uint16_t discard; uint16_t discard;
if(!buf->read_uint16(discard)) if (!buf->read_uint16(discard))
return false; return false;
if(!buf->read_uint16(rr_type)) if (!buf->read_uint16(rr_type))
{ {
llarp::LogDebug("failed to decode rr type"); llarp::LogDebug("failed to decode rr type");
return false; return false;
} }
if(!buf->read_uint16(rr_class)) if (!buf->read_uint16(rr_class))
{ {
llarp::LogDebug("failed to decode rr class"); llarp::LogDebug("failed to decode rr class");
return false; return false;
} }
if(!buf->read_uint32(ttl)) if (!buf->read_uint32(ttl))
{ {
llarp::LogDebug("failed to decode ttl"); llarp::LogDebug("failed to decode ttl");
return false; return false;
} }
if(!DecodeRData(buf, rData)) if (!DecodeRData(buf, rData))
{ {
llarp::LogDebug("failed to decode rr rdata ", *this); llarp::LogDebug("failed to decode rr rdata ", *this);
return false; return false;
@ -95,11 +95,11 @@ namespace llarp
bool bool
ResourceRecord::HasCNameForTLD(const std::string& tld) const ResourceRecord::HasCNameForTLD(const std::string& tld) const
{ {
if(rr_type != qTypeCNAME) if (rr_type != qTypeCNAME)
return false; return false;
Name_t name; Name_t name;
llarp_buffer_t buf(rData); llarp_buffer_t buf(rData);
if(not DecodeName(&buf, name)) if (not DecodeName(&buf, name))
return false; return false;
return name.find(tld) != std::string::npos return name.find(tld) != std::string::npos
&& name.rfind(tld) == (name.size() - tld.size()) - 1; && name.rfind(tld) == (name.size() - tld.size()) - 1;

@ -12,10 +12,10 @@ namespace llarp
{ {
namespace dns namespace dns
{ {
using RRClass_t = uint16_t; using RRClass_t = uint16_t;
using RRType_t = uint16_t; using RRType_t = uint16_t;
using RR_RData_t = std::vector< byte_t >; using RR_RData_t = std::vector<byte_t>;
using RR_TTL_t = uint32_t; using RR_TTL_t = uint32_t;
struct ResourceRecord : public Serialize struct ResourceRecord : public Serialize
{ {

@ -8,14 +8,14 @@ namespace llarp
Serialize::~Serialize() = default; Serialize::~Serialize() = default;
bool bool
EncodeRData(llarp_buffer_t* buf, const std::vector< byte_t >& v) EncodeRData(llarp_buffer_t* buf, const std::vector<byte_t>& v)
{ {
if(v.size() > 65536) if (v.size() > 65536)
return false; return false;
uint16_t len = v.size(); uint16_t len = v.size();
if(!buf->put_uint16(len)) if (!buf->put_uint16(len))
return false; return false;
if(buf->size_left() < len) if (buf->size_left() < len)
return false; return false;
memcpy(buf->cur, v.data(), len); memcpy(buf->cur, v.data(), len);
buf->cur += len; buf->cur += len;
@ -23,16 +23,16 @@ namespace llarp
} }
bool bool
DecodeRData(llarp_buffer_t* buf, std::vector< byte_t >& v) DecodeRData(llarp_buffer_t* buf, std::vector<byte_t>& v)
{ {
uint16_t len; uint16_t len;
if(!buf->read_uint16(len)) if (!buf->read_uint16(len))
return false; return false;
size_t left = buf->size_left(); size_t left = buf->size_left();
if(left < len) if (left < len)
return false; return false;
v.resize(size_t(len)); v.resize(size_t(len));
if(len) if (len)
{ {
memcpy(v.data(), buf->cur, len); memcpy(v.data(), buf->cur, len);
buf->cur += len; buf->cur += len;

@ -24,10 +24,10 @@ namespace llarp
}; };
bool bool
EncodeRData(llarp_buffer_t* buf, const std::vector< byte_t >& rdata); EncodeRData(llarp_buffer_t* buf, const std::vector<byte_t>& rdata);
bool bool
DecodeRData(llarp_buffer_t* buf, std::vector< byte_t >& rdata); DecodeRData(llarp_buffer_t* buf, std::vector<byte_t>& rdata);
} // namespace dns } // namespace dns
} // namespace llarp } // namespace llarp

@ -9,19 +9,22 @@ namespace llarp
{ {
namespace dns namespace dns
{ {
Proxy::Proxy(llarp_ev_loop_ptr serverLoop, Logic_ptr serverLogic, Proxy::Proxy(
llarp_ev_loop_ptr clientLoop, Logic_ptr clientLogic, llarp_ev_loop_ptr serverLoop,
IQueryHandler* h) Logic_ptr serverLogic,
llarp_ev_loop_ptr clientLoop,
Logic_ptr clientLogic,
IQueryHandler* h)
: m_ServerLoop(std::move(serverLoop)) : m_ServerLoop(std::move(serverLoop))
, m_ClientLoop(std::move(clientLoop)) , m_ClientLoop(std::move(clientLoop))
, m_ServerLogic(std::move(serverLogic)) , m_ServerLogic(std::move(serverLogic))
, m_ClientLogic(std::move(clientLogic)) , m_ClientLogic(std::move(clientLogic))
, m_QueryHandler(h) , m_QueryHandler(h)
{ {
m_Client.user = this; m_Client.user = this;
m_Server.user = this; m_Server.user = this;
m_Client.tick = nullptr; m_Client.tick = nullptr;
m_Server.tick = nullptr; m_Server.tick = nullptr;
m_Client.recvfrom = &HandleUDPRecv_client; m_Client.recvfrom = &HandleUDPRecv_client;
m_Server.recvfrom = &HandleUDPRecv_server; m_Server.recvfrom = &HandleUDPRecv_server;
} }
@ -32,8 +35,7 @@ namespace llarp
} }
bool bool
Proxy::Start(const llarp::Addr addr, Proxy::Start(const llarp::Addr addr, const std::vector<llarp::Addr>& resolvers)
const std::vector< llarp::Addr >& resolvers)
{ {
m_Resolvers.clear(); m_Resolvers.clear();
m_Resolvers = resolvers; m_Resolvers = resolvers;
@ -51,42 +53,38 @@ namespace llarp
static Proxy::Buffer_t static Proxy::Buffer_t
CopyBuffer(const llarp_buffer_t& buf) CopyBuffer(const llarp_buffer_t& buf)
{ {
std::vector< byte_t > msgbuf(buf.sz); std::vector<byte_t> msgbuf(buf.sz);
std::copy_n(buf.base, buf.sz, msgbuf.data()); std::copy_n(buf.base, buf.sz, msgbuf.data());
return msgbuf; return msgbuf;
} }
void void
Proxy::HandleUDPRecv_server(llarp_udp_io* u, const sockaddr* from, Proxy::HandleUDPRecv_server(llarp_udp_io* u, const sockaddr* from, ManagedBuffer buf)
ManagedBuffer buf)
{ {
const llarp::Addr addr(*from); const llarp::Addr addr(*from);
Buffer_t msgbuf = CopyBuffer(buf.underlying); Buffer_t msgbuf = CopyBuffer(buf.underlying);
auto self = static_cast< Proxy* >(u->user)->shared_from_this(); auto self = static_cast<Proxy*>(u->user)->shared_from_this();
// yes we use the server loop here because if the server loop is not the // yes we use the server loop here because if the server loop is not the
// client loop we'll crash again // client loop we'll crash again
LogicCall(self->m_ServerLogic, [self, addr, msgbuf]() { LogicCall(
self->HandlePktServer(addr, msgbuf); self->m_ServerLogic, [self, addr, msgbuf]() { self->HandlePktServer(addr, msgbuf); });
});
} }
void void
Proxy::HandleUDPRecv_client(llarp_udp_io* u, const sockaddr* from, Proxy::HandleUDPRecv_client(llarp_udp_io* u, const sockaddr* from, ManagedBuffer buf)
ManagedBuffer buf)
{ {
const llarp::Addr addr(*from); const llarp::Addr addr(*from);
Buffer_t msgbuf = CopyBuffer(buf.underlying); Buffer_t msgbuf = CopyBuffer(buf.underlying);
auto self = static_cast< Proxy* >(u->user)->shared_from_this(); auto self = static_cast<Proxy*>(u->user)->shared_from_this();
LogicCall(self->m_ServerLogic, [self, addr, msgbuf]() { LogicCall(
self->HandlePktClient(addr, msgbuf); self->m_ServerLogic, [self, addr, msgbuf]() { self->HandlePktClient(addr, msgbuf); });
});
} }
llarp::Addr llarp::Addr
Proxy::PickRandomResolver() const Proxy::PickRandomResolver() const
{ {
const size_t sz = m_Resolvers.size(); const size_t sz = m_Resolvers.size();
if(sz <= 1) if (sz <= 1)
return m_Resolvers[0]; return m_Resolvers[0];
auto itr = m_Resolvers.begin(); auto itr = m_Resolvers.begin();
std::advance(itr, llarp::randint() % sz); std::advance(itr, llarp::randint() % sz);
@ -103,11 +101,11 @@ namespace llarp
{ {
auto self = shared_from_this(); auto self = shared_from_this();
LogicCall(m_ServerLogic, [to, msg, self]() { LogicCall(m_ServerLogic, [to, msg, self]() {
std::array< byte_t, 1500 > tmp = {{0}}; std::array<byte_t, 1500> tmp = {{0}};
llarp_buffer_t buf(tmp); llarp_buffer_t buf(tmp);
if(msg.Encode(&buf)) if (msg.Encode(&buf))
{ {
buf.sz = buf.cur - buf.base; buf.sz = buf.cur - buf.base;
buf.cur = buf.base; buf.cur = buf.base;
llarp_ev_udp_sendto(&self->m_Server, to, buf); llarp_ev_udp_sendto(&self->m_Server, to, buf);
} }
@ -121,11 +119,11 @@ namespace llarp
{ {
auto self = shared_from_this(); auto self = shared_from_this();
LogicCall(m_ClientLogic, [to, msg, self]() { LogicCall(m_ClientLogic, [to, msg, self]() {
std::array< byte_t, 1500 > tmp = {{0}}; std::array<byte_t, 1500> tmp = {{0}};
llarp_buffer_t buf(tmp); llarp_buffer_t buf(tmp);
if(msg.Encode(&buf)) if (msg.Encode(&buf))
{ {
buf.sz = buf.cur - buf.base; buf.sz = buf.cur - buf.base;
buf.cur = buf.base; buf.cur = buf.base;
llarp_ev_udp_sendto(&self->m_Client, to, buf); llarp_ev_udp_sendto(&self->m_Client, to, buf);
} }
@ -139,27 +137,26 @@ namespace llarp
{ {
llarp_buffer_t pkt(buf); llarp_buffer_t pkt(buf);
MessageHeader hdr; MessageHeader hdr;
if(!hdr.Decode(&pkt)) if (!hdr.Decode(&pkt))
{ {
llarp::LogWarn("failed to parse dns header from ", from); llarp::LogWarn("failed to parse dns header from ", from);
return; return;
} }
TX tx = {hdr.id, from}; TX tx = {hdr.id, from};
auto itr = m_Forwarded.find(tx); auto itr = m_Forwarded.find(tx);
if(itr == m_Forwarded.end()) if (itr == m_Forwarded.end())
return; return;
const Addr requester = itr->second; const Addr requester = itr->second;
auto self = shared_from_this(); auto self = shared_from_this();
Message msg(hdr); Message msg(hdr);
if(msg.Decode(&pkt)) if (msg.Decode(&pkt))
{ {
if(m_QueryHandler && m_QueryHandler->ShouldHookDNSMessage(msg)) if (m_QueryHandler && m_QueryHandler->ShouldHookDNSMessage(msg))
{ {
msg.hdr_id = itr->first.txid; msg.hdr_id = itr->first.txid;
if(!m_QueryHandler->HandleHookedDNSMessage( if (!m_QueryHandler->HandleHookedDNSMessage(
std::move(msg), std::move(msg),
std::bind(&Proxy::SendServerMessageTo, self, requester, std::bind(&Proxy::SendServerMessageTo, self, requester, std::placeholders::_1)))
std::placeholders::_1)))
{ {
llarp::LogWarn("failed to handle hooked dns"); llarp::LogWarn("failed to handle hooked dns");
} }
@ -180,16 +177,16 @@ namespace llarp
{ {
MessageHeader hdr; MessageHeader hdr;
llarp_buffer_t pkt(buf); llarp_buffer_t pkt(buf);
if(!hdr.Decode(&pkt)) if (!hdr.Decode(&pkt))
{ {
llarp::LogWarn("failed to parse dns header from ", from); llarp::LogWarn("failed to parse dns header from ", from);
return; return;
} }
TX tx = {hdr.id, from}; TX tx = {hdr.id, from};
auto itr = m_Forwarded.find(tx); auto itr = m_Forwarded.find(tx);
Message msg(hdr); Message msg(hdr);
if(!msg.Decode(&pkt)) if (!msg.Decode(&pkt))
{ {
llarp::LogWarn("failed to parse dns message from ", from); llarp::LogWarn("failed to parse dns message from ", from);
return; return;
@ -200,10 +197,10 @@ namespace llarp
// thankfully mozilla added a backdoor that allows ISPs to turn it off // thankfully mozilla added a backdoor that allows ISPs to turn it off
// so we disable DoH for firefox using mozilla's ISP backdoor // so we disable DoH for firefox using mozilla's ISP backdoor
// see: https://github.com/loki-project/loki-network/issues/832 // see: https://github.com/loki-project/loki-network/issues/832
for(const auto& q : msg.questions) for (const auto& q : msg.questions)
{ {
// is this firefox looking for their backdoor record? // is this firefox looking for their backdoor record?
if(q.IsName("use-application-dns.net")) if (q.IsName("use-application-dns.net"))
{ {
// yea it is, let's turn off DoH because god is dead. // yea it is, let's turn off DoH because god is dead.
msg.AddNXReply(); msg.AddNXReply();
@ -214,17 +211,16 @@ namespace llarp
} }
auto self = shared_from_this(); auto self = shared_from_this();
if(m_QueryHandler && m_QueryHandler->ShouldHookDNSMessage(msg)) if (m_QueryHandler && m_QueryHandler->ShouldHookDNSMessage(msg))
{ {
if(!m_QueryHandler->HandleHookedDNSMessage( if (!m_QueryHandler->HandleHookedDNSMessage(
std::move(msg), std::move(msg),
std::bind(&Proxy::SendServerMessageTo, self, from, std::bind(&Proxy::SendServerMessageTo, self, from, std::placeholders::_1)))
std::placeholders::_1)))
{ {
llarp::LogWarn("failed to handle hooked dns"); llarp::LogWarn("failed to handle hooked dns");
} }
} }
else if(m_Resolvers.size() == 0) else if (m_Resolvers.size() == 0)
{ {
// no upstream resolvers // no upstream resolvers
// let's serv fail it // let's serv fail it
@ -232,10 +228,10 @@ namespace llarp
SendServerMessageTo(from, std::move(msg)); SendServerMessageTo(from, std::move(msg));
} }
else if(itr == m_Forwarded.end()) else if (itr == m_Forwarded.end())
{ {
// new forwarded query // new forwarded query
tx.from = PickRandomResolver(); tx.from = PickRandomResolver();
m_Forwarded[tx] = from; m_Forwarded[tx] = from;
LogicCall(m_ClientLogic, [=] { LogicCall(m_ClientLogic, [=] {
// do query // do query

@ -24,34 +24,33 @@ namespace llarp
/// handle a hooked message /// handle a hooked message
virtual bool virtual bool
HandleHookedDNSMessage(Message query, HandleHookedDNSMessage(Message query, std::function<void(Message)> sendReply) = 0;
std::function< void(Message) > sendReply) = 0;
}; };
struct Proxy : public std::enable_shared_from_this< Proxy > struct Proxy : public std::enable_shared_from_this<Proxy>
{ {
using Logic_ptr = std::shared_ptr< Logic >; using Logic_ptr = std::shared_ptr<Logic>;
Proxy(llarp_ev_loop_ptr serverLoop, Logic_ptr serverLogic, Proxy(
llarp_ev_loop_ptr clientLoop, Logic_ptr clientLogic, llarp_ev_loop_ptr serverLoop,
IQueryHandler* handler); Logic_ptr serverLogic,
llarp_ev_loop_ptr clientLoop,
Logic_ptr clientLogic,
IQueryHandler* handler);
bool bool
Start(const llarp::Addr addr, Start(const llarp::Addr addr, const std::vector<llarp::Addr>& resolvers);
const std::vector< llarp::Addr >& resolvers);
void void
Stop(); Stop();
using Buffer_t = std::vector< uint8_t >; using Buffer_t = std::vector<uint8_t>;
private: private:
/// low level packet handler /// low level packet handler
static void static void
HandleUDPRecv_client(llarp_udp_io*, const struct sockaddr*, HandleUDPRecv_client(llarp_udp_io*, const struct sockaddr*, ManagedBuffer);
ManagedBuffer);
static void static void
HandleUDPRecv_server(llarp_udp_io*, const struct sockaddr*, HandleUDPRecv_server(llarp_udp_io*, const struct sockaddr*, ManagedBuffer);
ManagedBuffer);
/// low level ticker /// low level ticker
static void static void
@ -83,7 +82,7 @@ namespace llarp
Logic_ptr m_ServerLogic; Logic_ptr m_ServerLogic;
Logic_ptr m_ClientLogic; Logic_ptr m_ClientLogic;
IQueryHandler* m_QueryHandler; IQueryHandler* m_QueryHandler;
std::vector< llarp::Addr > m_Resolvers; std::vector<llarp::Addr> m_Resolvers;
struct TX struct TX
{ {
@ -107,7 +106,7 @@ namespace llarp
}; };
// maps tx to who to send reply to // maps tx to who to send reply to
std::unordered_map< TX, llarp::Addr, TX::Hash > m_Forwarded; std::unordered_map<TX, llarp::Addr, TX::Hash> m_Forwarded;
}; };
} // namespace dns } // namespace dns
} // namespace llarp } // namespace llarp

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save