Merge pull request #576 from majestrate/master

recent changes
pull/584/head
Jeff 5 years ago committed by GitHub
commit b617851dec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -108,9 +108,7 @@ if(WIN32)
target_link_libraries(${PLATFORM_LIB} PUBLIC iphlpapi)
endif()
set(DNSLIB_SRC
dns/dotlokilookup.cpp
dns/dns.cpp
dns/iptracker.cpp
dns/message.cpp
dns/name.cpp
dns/query.cpp
@ -172,6 +170,7 @@ set(LIB_SRC
handlers/exit.cpp
handlers/null.cpp
handlers/tun.cpp
hook/shell.cpp
iwp/linklayer.cpp
iwp/outermessage.cpp
iwp/iwp.cpp

@ -4,7 +4,6 @@
#include <config.hpp>
#include <crypto/crypto_libsodium.hpp>
#include <dht/context.hpp>
#include <dns/dotlokilookup.hpp>
#include <dnsd.hpp>
#include <ev/ev.hpp>
#include <metrics/metrictank_publisher.hpp>
@ -464,18 +463,6 @@ extern "C"
ptr->ctx->HandleSignal(sig);
}
void
llarp_main_inject_vpn_fd(struct llarp_main *ptr, int rfd, int wfd)
{
llarp::handlers::TunEndpoint *tun =
ptr->ctx->router->hiddenServiceContext().getFirstTun();
if(!tun)
return;
if(!tun->Promise)
return;
tun->Promise->Set({rfd, wfd});
}
int
llarp_main_setup(struct llarp_main *ptr)
{
@ -538,6 +525,7 @@ extern "C"
return ptr->ctx->LoadDatabase();
}
/*
int
llarp_main_iterateDatabase(struct llarp_main *ptr, struct llarp_nodedb_iter i)
{
@ -611,13 +599,6 @@ extern "C"
// llarp_dht_lookup_router(ptr->ctx->router->dht, job);
}
bool
main_router_prefetch(struct llarp_main *ptr,
const llarp::service::Address &addr)
{
auto &endpoint = ptr->ctx->router->hiddenServiceContext();
return endpoint.Prefetch(addr);
}
llarp::handlers::TunEndpoint *
main_router_getFirstTunEndpoint(struct llarp_main *ptr)
@ -640,11 +621,12 @@ extern "C"
return ptr->ctx->router->hiddenServiceContext().getRange();
}
*/
const char *
handleBaseCmdLineArgs(int argc, char *argv[])
{
// clang-format off
// clang-format off
cxxopts::Options options(
"lokinet",
"Lokinet is a private, decentralized and IP based overlay network for the internet"
@ -652,9 +634,9 @@ extern "C"
options.add_options()
("c,config", "Config file", cxxopts::value< std::string >()->default_value("daemon.ini"))
("o,logLevel", "logging level");
// clang-format on
// clang-format on
auto result = options.parse(argc, argv);
auto result = options.parse(argc, argv);
std::string logLevel = result["logLevel"].as< std::string >();
if(logLevel == "debug")
@ -674,9 +656,10 @@ extern "C"
cSetLogLevel(eLogError);
}
// this isn't thread safe, but reconfiguring during run is likely unsafe either way
static std::string confname = result["config"].as< std::string >();
// this isn't thread safe, but reconfiguring during run is likely unsafe
// either way
static std::string confname = result["config"].as< std::string >();
return confname.c_str();
return confname.c_str();
}
}

@ -107,7 +107,8 @@ namespace llarp
template < typename User >
struct AsyncFrameDecrypter
{
using DecryptHandler = std::function< void(llarp_buffer_t*, User*) >;
using User_ptr = std::shared_ptr< User >;
using DecryptHandler = std::function< void(llarp_buffer_t*, User_ptr) >;
static void
Decrypt(void* user)
@ -119,10 +120,11 @@ namespace llarp
{
auto buf = ctx->target.Buffer();
buf->cur = buf->base + EncryptedFrameOverheadSize;
ctx->result(buf, ctx->context);
ctx->result(buf, ctx->user);
}
else
ctx->result(nullptr, ctx->context);
ctx->result(nullptr, ctx->user);
ctx->user = nullptr;
}
AsyncFrameDecrypter(llarp::Crypto* c, const SecretKey& secretkey,
@ -132,17 +134,17 @@ namespace llarp
}
DecryptHandler result;
User* context;
User_ptr user;
llarp::Crypto* crypto;
const SecretKey& seckey;
EncryptedFrame target;
void
AsyncDecrypt(llarp_threadpool* worker, const EncryptedFrame& frame,
User* user)
User_ptr u)
{
target = frame;
context = user;
target = frame;
user = u;
llarp_threadpool_queue_job(worker, {this, &Decrypt});
}
};

@ -1,476 +0,0 @@
#include <dns/dotlokilookup.hpp>
#include <handlers/tun.hpp>
#include <service/context.hpp>
#include <util/logic.hpp>
std::string const default_chars =
"abcdefghijklmnaoqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
#include <random>
std::string
random_string(size_t len = 15, std::string const &allowed_chars = default_chars)
{
std::mt19937_64 gen{std::random_device()()};
std::uniform_int_distribution< size_t > dist{0, allowed_chars.length() - 1};
std::string ret;
std::generate_n(std::back_inserter(ret), len,
[&] { return allowed_chars[dist(gen)]; });
return ret;
}
struct check_query_simple_request
{
// already inside request
// const struct sockaddr *from; // source
const dnsd_question_request *request;
};
std::unordered_map< std::string, struct dnsd_query_hook_response * >
loki_tld_lookup_cache;
static bool
decode_request_name(const std::string &name, llarp::AlignedBuffer< 32 > &addr,
bool &isSNode)
{
llarp::service::Address serviceAddr;
llarp::RouterID snodeAddr;
auto pos = name.find(".snode");
if(pos != std::string::npos)
{
if(!llarp::HexDecode(name.substr(0, pos).c_str(), serviceAddr.begin(),
serviceAddr.size()))
{
return false;
}
addr = snodeAddr;
isSNode = true;
}
else
{
if(!serviceAddr.FromString(name))
{
return false;
}
addr = serviceAddr;
isSNode = false;
}
return true;
}
void
llarp_dotlokilookup_checkQuery(void *u, __attribute__((unused)) uint64_t orig,
uint64_t left)
{
if(left)
return;
// struct check_query_request *request = static_cast< struct
// check_query_request * >(u);
struct check_query_simple_request *qr =
static_cast< struct check_query_simple_request * >(u);
dotLokiLookup *dll = (dotLokiLookup *)qr->request->context->user;
if(!dll)
{
llarp::LogError("DNSd dotLokiLookup is not configured");
write404_dnss_response(qr->request);
delete qr;
return;
}
// we do have result
// if so send that
// else
// if we have a free private ip, send that
/*
// cache hit
auto itr = loki_tld_lookup_cache.find(addr.ToString());
if(itr != loki_tld_lookup_cache.end())
{
llarp::LogDebug("Found in .loki lookup cache");
writesend_dnss_response(itr->second->returnThis, qr->from, qr->request);
delete qr;
return;
}
struct dns_pointer *free_private = dns_iptracker_get_free(dll->ip_tracker);
if(free_private)
{
*/
// in_addr ip_address = ((sockaddr_in *)free_private->hostResult)->sin_addr;
llarp::service::Context *routerHiddenServiceContext =
(llarp::service::Context *)dll->user;
if(!routerHiddenServiceContext)
{
llarp::LogWarn("dotLokiLookup user isnt a service::Context: ", dll->user);
write404_dnss_response(qr->request);
delete qr;
return;
}
llarp::huint32_t serviceIP;
llarp::AlignedBuffer< 32 > addr;
bool isSNode = false;
if(!decode_request_name(qr->request->question.name, addr, isSNode))
{
llarp::LogWarn("decode_request_name failed");
write404_dnss_response(qr->request);
delete qr;
return;
}
if(!routerHiddenServiceContext->FindBestAddressFor(addr, isSNode, serviceIP))
{
llarp::LogWarn("dotLokiLookup failed to map address");
write404_dnss_response(qr->request);
delete qr;
return;
}
/*
bool mapResult = routerHiddenServiceContext->MapAddressAll(
addr, free_private->hostResult);
if(!mapResult)
{
llarp::LogWarn("dotLokiLookup failed to map address");
write404_dnss_response(qr->from, qr->request);
delete qr;
return;
}
*/
// make a dnsd_query_hook_response for the cache
dnsd_query_hook_response *response = new dnsd_query_hook_response;
response->dontLookUp = true;
response->dontSendResponse = false;
// llarp::Addr test(*free_private->hostResult.getSockAddr());
// llarp::LogInfo("IP Test: ", test);
// response->returnThis = &free_private->hostResult;
response->returnThis = serviceIP;
llarp::LogInfo("Saving ", qr->request->question.name);
loki_tld_lookup_cache[qr->request->question.name] = response;
// we can't delete response now...
/*
llarp::handlers::TunEndpoint *tunEndpoint =
(llarp::handlers::TunEndpoint *)dll->user;
if (!tunEndpoint)
{
llarp::LogWarn("dotLokiLookup user isnt a tunEndpoint: ", dll->user);
return;
}
bool mapResult = tunEndpoint->MapAddress(addr,
free_private->hostResult.tohl()); if(!mapResult)
{
delete qr;
return;
}
*/
llarp::huint32_t foundAddr;
if(!routerHiddenServiceContext->FindBestAddressFor(addr, isSNode, foundAddr))
{
write404_dnss_response(qr->request);
delete qr;
return;
}
// make a dnsd_query_hook_response for the cache
/*
dnsd_query_hook_response *response = new dnsd_query_hook_response;
response->dontLookUp = true;
response->dontSendResponse = false;
loki_tld_lookup_cache[addr.ToString()]=response;
*/
// we can't delete response now...
// sockaddr_in saddr;
// saddr.sin_family = AF_INET;
// saddr.sin_addr.s_addr = llarp::xhtonl(foundAddr).n;
// FIXME: flush cache to disk
// on crash we'll need to bring up all the same IPs we assigned before...
writesend_dnss_response(&foundAddr, qr->request);
delete qr;
return;
}
std::vector< std::string >
split(std::string str)
{
size_t pos = 0;
std::string token;
std::string s(str);
std::vector< std::string > tokens;
while((pos = s.find(".")) != std::string::npos)
{
token = s.substr(0, pos);
// llarp::LogInfo("token [", token, "]");
tokens.push_back(token);
s.erase(0, pos + 1);
}
token = s.substr(0, pos);
tokens.push_back(token);
// llarp::LogInfo("token [", token, "]");
return tokens;
}
struct reverse_handler_iter_context
{
std::string lName;
// const struct sockaddr *from; // aready inside dnsd_question_request
const dnsd_question_request *request;
};
#if defined(ANDROID) || defined(RPI)
static int
stoi(const std::string &s)
{
return atoi(s.c_str());
}
#endif
bool
ReverseHandlerIter(struct llarp::service::Context::endpoint_iter *endpointCfg)
{
reverse_handler_iter_context *context =
(reverse_handler_iter_context *)endpointCfg->user;
// llarp::LogInfo("context ", context->request->question.name);
// llarp::LogInfo("Checking ", lName);
llarp::handlers::TunEndpoint *tunEndpoint =
(llarp::handlers::TunEndpoint *)endpointCfg->endpoint;
if(!tunEndpoint)
{
llarp::LogError("No tunnel endpoint found");
return true; // still continue
}
// llarp::LogInfo("for ", tunEndpoint->tunif.ifaddr);
std::string checkStr(tunEndpoint->tunif.ifaddr);
std::vector< std::string > tokensSearch = split(context->lName);
std::vector< std::string > tokensCheck = split(checkStr);
// well the tunif is just one ip on a network range...
// support "b._dns-sd._udp.0.0.200.10.in-addr.arpa"
size_t searchTokens = tokensSearch.size();
// if the query has five or fewer levels,
// tack on leading '0.'s to form a minimum six-level
// PTR query -rick
if(searchTokens < 6)
{
switch(searchTokens)
{
case 5:
tokensSearch.clear();
context->lName.insert(0, "0.");
tokensSearch = split(context->lName);
searchTokens = tokensSearch.size();
break;
case 4:
tokensSearch.clear();
context->lName.insert(0, "0.0.");
tokensSearch = split(context->lName);
searchTokens = tokensSearch.size();
break;
case 3:
tokensSearch.clear();
context->lName.insert(0, "0.0.0.");
tokensSearch = split(context->lName);
searchTokens = tokensSearch.size();
break;
default:
llarp::LogError("invalid PTR query: ", context->lName);
break;
}
}
// this expression assumes a six-level name
std::string searchIp = tokensSearch[searchTokens - 3] + "."
+ tokensSearch[searchTokens - 4] + "." + tokensSearch[searchTokens - 5]
+ "." + tokensSearch[searchTokens - 6];
std::string checkIp = tokensCheck[0] + "." + tokensCheck[1] + "."
+ tokensCheck[2] + "." + tokensCheck[3];
llarp::LogDebug(searchIp, " vs ", checkIp);
llarp::IPRange range =
llarp::iprange_ipv4(std::stoi(tokensCheck[0]), std::stoi(tokensCheck[1]),
std::stoi(tokensCheck[2]), std::stoi(tokensCheck[3]),
tunEndpoint->tunif.netmask); // create range
llarp::huint32_t searchIPv4 = llarp::ipaddr_ipv4_bits(
std::stoi(tokensSearch[searchTokens - 3]),
std::stoi(tokensSearch[searchTokens - 4]),
std::stoi(tokensSearch[searchTokens - 5]),
std::stoi(tokensSearch[searchTokens - 6])); // create ip
// bool inRange = range.Contains(searchAddr.xtohl());
bool inRange = range.Contains(searchIPv4);
llarp::Addr searchAddr(searchIp);
llarp::Addr checkAddr(checkIp);
llarp::LogInfo(searchIPv4, " vs ", range, " = ",
inRange ? "inRange" : "not match");
if(inRange)
{
llarp::AlignedBuffer< 32 > addr =
tunEndpoint->ObtainAddrForIP< llarp::AlignedBuffer< 32 > >(searchIPv4,
false);
if(addr.IsZero())
{
addr = tunEndpoint->ObtainAddrForIP< llarp::AlignedBuffer< 32 > >(
searchIPv4, true);
if(!addr.IsZero())
{
char stack[128] = {0};
std::string saddr = llarp::HexEncode(addr, stack);
saddr += ".snode";
writesend_dnss_revresponse(saddr, context->request);
}
else
write404_dnss_response(context->request);
}
else
{
llarp::service::Address saddr(addr);
// llarp::LogInfo("Returning [", saddr.ToString(), "]");
writesend_dnss_revresponse(saddr.ToString(), context->request);
}
return false;
}
return true; // we don't do anything with the result yet
}
static bool
should_intercept_query_with_name(const std::string &lName)
{
// null terminated list
static const char *const matches[] = {".loki", ".snode", ".loki.", ".snode.",
0};
size_t idx = 0;
while(matches[idx])
{
std::string match_str(matches[idx]);
if(lName.substr(lName.length() - match_str.length()) == match_str)
return true;
++idx;
}
return false;
}
dnsd_query_hook_response *
llarp_dotlokilookup_handler(std::string name,
const dnsd_question_request *request)
{
dnsd_query_hook_response *response = new dnsd_query_hook_response;
response->dontLookUp = false;
response->dontSendResponse = false;
response->returnThis.h = 0;
llarp::LogDebug("Hooked ", name);
std::string lName = name;
std::transform(lName.begin(), lName.end(), lName.begin(), ::tolower);
// llarp::LogDebug("Transformed ", lName);
// 253.0.200.10.in-addr.arpa
if(lName.find(".in-addr.arpa") != std::string::npos)
{
// llarp::LogDebug("Checking ", lName);
dotLokiLookup *dll = (dotLokiLookup *)request->context->user;
llarp::service::Context *routerHiddenServiceContext =
(llarp::service::Context *)dll->user;
if(!routerHiddenServiceContext)
{
llarp::LogWarn("dotLokiLookup user isnt a service::Context: ", dll->user);
return response;
}
// llarp::LogDebug("Starting rev iter for ", lName);
// which range?
// for each tun interface
struct reverse_handler_iter_context context;
context.lName = lName;
// context.from = request->from;
context.request = request;
struct llarp::service::Context::endpoint_iter i;
i.user = &context;
i.index = 0;
i.visit = &ReverseHandlerIter;
bool res = routerHiddenServiceContext->iterate(i);
if(!res)
{
llarp::LogDebug("Reverse is ours");
response->dontLookUp = true;
response->dontSendResponse = true; // should have already sent it
}
else
{
llarp::LogInfo("Reverse is not ours");
}
}
else if(should_intercept_query_with_name(lName))
{
llarp::LogInfo("Detect Loki Lookup for ", lName);
auto cache_check = loki_tld_lookup_cache.find(lName);
if(cache_check != loki_tld_lookup_cache.end())
{
// was in cache
llarp::LogInfo("Reused address from LokiLookupCache");
// FIXME: avoid the response allocation if you could
delete response;
return cache_check->second;
}
// decode address
llarp::AlignedBuffer< 32 > addr;
bool isSNode = false;
if(!decode_request_name(lName, addr, isSNode))
{
response->dontLookUp = true;
return response;
}
dotLokiLookup *dll = (dotLokiLookup *)request->context->user;
llarp::service::Context *routerHiddenServiceContext =
(llarp::service::Context *)dll->user;
if(!routerHiddenServiceContext)
{
llarp::LogWarn("dotLokiLookup user isnt a service::Context: ", dll->user);
return response;
}
// start path build early (if you're looking it up, you're probably going to
// use it)
// main_router_prefetch(ctx, addr);
// schedule future response
check_query_simple_request *qr = new check_query_simple_request;
// qr->from = request->from;
qr->request = request;
auto tun = routerHiddenServiceContext->getFirstTun();
if(isSNode)
{
if(tun->HasPathToSNode(addr.as_array()))
{
llarp_dotlokilookup_checkQuery(qr, 0, 0);
response->dontSendResponse = true; // will send it shortly
return response;
}
}
else
{
if(tun->HasPathToService(llarp::service::Address(addr)))
{
llarp_dotlokilookup_checkQuery(qr, 0, 0);
response->dontSendResponse = true; // will send it shortly
return response;
}
}
// nslookup on osx is about 5 sec before a retry, 2s on linux
request->context->client.logic->call_later(
{2000, qr, &llarp_dotlokilookup_checkQuery});
response->dontSendResponse = true; // will send it shortly
}
return response;
}

@ -1,39 +0,0 @@
#ifndef LLARP_DNS_DOTLOKILOOKUP_HPP
#define LLARP_DNS_DOTLOKILOOKUP_HPP
#include <dnsd.hpp>
#include <service/address.hpp>
using map_address_hook_func =
std::function< bool(const byte_t *addr, bool isSNode, uint32_t ip) >;
/// dotLokiLookup context/config
struct dotLokiLookup
{
/// for timers (MAYBEFIXME? maybe we decouple this, yes pls have a generic
/// passed in)
// we can use DNSc for access to the logic
llarp::Logic *logic;
/// which ip tracker to use
struct dns_iptracker *ip_tracker;
/// tunEndpoint
// llarp::handlers::TunEndpoint *tunEndpoint; // is this even needed here?
void *user; // well dotLokiLookup current uses it to access the tun if
// pointer to tunendpoint properties?
// llarp::service::Context *hiddenServiceContext;
// need a way to reference
// 1. mapaddress
map_address_hook_func map_address_handler;
// std::function< bool(const llarp::service::Address &addr, uint32_t ip),
// llarp::handlers::TunEndpoint * > callback;
// 2. prefetch
};
dnsd_query_hook_response *
llarp_dotlokilookup_handler(std::string name,
const dnsd_question_request *request);
#endif

@ -1,197 +0,0 @@
#include <dns/iptracker.hpp>
dns_iptracker g_dns_iptracker;
void
dns_iptracker_init()
{
/*
g_dns_iptracker.interfaces = llarp_getPrivateIfs();
llarp::LogInfo("Interface uses 10.x.x.x? ",
g_dns_iptracker.interfaces.ten ? "Yes" : "No");
g_dns_iptracker.used_privates = g_dns_iptracker.interfaces;
llarp::LogInfo("We used 10.x.x.x? ",
g_dns_iptracker.used_privates.ten ? "Yes" : "No");
*/
// disable all possibilities unless you setup a tunGateway
g_dns_iptracker.used_privates.ten = true;
g_dns_iptracker.used_privates.oneSeven = true;
g_dns_iptracker.used_privates.oneNine = true;
}
// not sure we want tunGatewayIP... we'll know when we get further
bool
dns_iptracker_setup_dotLokiLookup(dotLokiLookup *dll, ABSL_ATTRIBUTE_UNUSED
llarp::huint32_t tunGatewayIp)
{
dll->ip_tracker = &g_dns_iptracker;
return true;
}
// FIXME: pass in b32addr of client
bool
dns_iptracker_setup(dns_iptracker *iptracker, llarp::huint32_t tunGatewayIp)
{
if(!iptracker)
iptracker = &g_dns_iptracker; // FIXME: god forgive I'm tired
// struct in_addr *addr = tunGatewayIp.addr4();
// unsigned char *ip = (unsigned char *)&(addr->s_addr);
unsigned char *ip = (unsigned char *)&(tunGatewayIp.h);
/*
llarp::LogInfo("iptracker setup: (", std::to_string(ip[0]), ").[",
std::to_string(ip[1]), '.', std::to_string(ip[2]), "].",
std::to_string(ip[3]));
*/
std::unique_ptr< ip_range > range(new ip_range);
range->octet2 = ip[1]; // 2nd octet
range->octet3 = ip[2]; // 3rd octet
// FIXME: look up any static mappings to discount
range->left = 252;
// 4th octet, probably 1, set it
struct dns_pointer *result = new dns_pointer;
result->hostResult = tunGatewayIp;
// tunGatewayIp.CopyInto(result->hostResult);
// result->b32addr = ; // FIXME: should be our HS addr
range->used[ip[3]] = result; // claim tun IP
// save tun range in tracker
// FIXME: forcing one and only one range
if(ip[0] == 10)
{
iptracker->used_ten_ips.push_back(std::move(range));
iptracker->used_privates.ten = false;
}
else if(ip[0] == 172)
{
iptracker->used_seven_ips.push_back(std::move(range));
iptracker->used_privates.oneSeven = false;
}
else if(ip[0] == 192)
{
iptracker->used_nine_ips.push_back(std::move(range));
iptracker->used_privates.oneNine = false;
}
else
{
return false;
}
return true;
}
inline struct dns_pointer *
dns_iptracker_allocate_range(std::unique_ptr< ip_range > &range, uint8_t first)
{
// we have an IP
llarp::LogDebug("Range has ", (unsigned int)range->left, " ips left");
range->left--; // use it up
struct dns_pointer *result = new dns_pointer;
llarp::Addr ip(first, range->octet2, range->octet3,
range->left + 2); // why plus 2? to start at .2
llarp::LogDebug("Allocated ", ip);
// result->hostResult = new sockaddr;
// ip.CopyInto(result->hostResult);
result->hostResult = ip.xtohl();
// make an address and place into this sockaddr
range->used[range->left + 2] = result;
return result;
}
struct dns_pointer *
dns_iptracker_check_range(std::vector< std::unique_ptr< ip_range > > &ranges,
uint8_t first)
{
// tens not all used up
if(ranges.size())
{
// FIXME: maybe find_if where left not 0
// find a range
for(auto it = ranges.begin(); it != ranges.end(); ++it)
{
if((*it)->left)
{
struct dns_pointer *result = dns_iptracker_allocate_range(*it, first);
if(!(*it)->left)
{
// all used up
// FIXME: are there any more octets available?
}
return result;
}
}
}
else
{
// create one
std::unique_ptr< ip_range > new_range(new ip_range);
new_range->octet2 = 0;
switch(first)
{
case 172:
{
// FIXME: goes up to 31...
new_range->octet2 = 16;
break;
}
case 192:
{
new_range->octet2 = 168;
break;
}
}
new_range->octet3 = 0; // FIXME: counter (0-255)
// CHECK: planning a /24 but maybe that's too wide for broadcasts
new_range->left = 252; // 0 is net, 1 is gw, 255 is broadcast
ranges.push_back(std::move(new_range));
// don't need to check if we're out since this is fresh range
return dns_iptracker_allocate_range(ranges[0], first);
}
return nullptr;
}
struct dns_pointer *
dns_iptracker_get_free()
{
return dns_iptracker_get_free(&g_dns_iptracker);
}
struct dns_pointer *
dns_iptracker_get_free(dns_iptracker *iptracker)
{
llarp::LogInfo("Was 10.x.x.x already in-use on start? ",
iptracker->used_privates.ten ? "Yes" : "No");
if(!iptracker->used_privates.ten)
{
struct dns_pointer *test =
dns_iptracker_check_range(iptracker->used_ten_ips, 10);
if(test)
{
return test;
}
}
llarp::LogInfo("Was 172.16.x.x already in-use on start? ",
iptracker->used_privates.oneSeven ? "Yes" : "No");
if(!iptracker->used_privates.oneSeven)
{
struct dns_pointer *test =
dns_iptracker_check_range(iptracker->used_seven_ips, 172);
if(test)
{
return test;
}
}
llarp::LogInfo("Was 192.168.x.x already in-use on start? ",
iptracker->used_privates.oneNine ? "Yes" : "No");
if(!iptracker->used_privates.oneNine)
{
struct dns_pointer *test =
dns_iptracker_check_range(iptracker->used_nine_ips, 192);
if(test)
{
return test;
}
}
return nullptr;
}

@ -1,56 +0,0 @@
#ifndef LLARP_DNSIPTRACKER_HPP
#define LLARP_DNSIPTRACKER_HPP
#include <dns/dotlokilookup.hpp>
#include <net/net.hpp>
#include <service/address.hpp>
#include <map>
#include <vector>
// either a request or response?
// neither, it's a result set row
struct dns_pointer
{
llarp::huint32_t hostResult;
llarp::service::Address b32addr;
// we could store the timeout at which we expect it to be available
// or a list of pending requests for it
};
struct ip_range
{
uint8_t octet2;
uint8_t octet3;
uint8_t left;
std::unordered_map< uint8_t, dns_pointer * > used;
};
struct dns_iptracker
{
struct privatesInUse interfaces;
struct privatesInUse used_privates;
std::vector< std::unique_ptr< ip_range > > used_ten_ips;
std::vector< std::unique_ptr< ip_range > > used_seven_ips;
std::vector< std::unique_ptr< ip_range > > used_nine_ips;
// make it easier to find a entry
std::vector< std::unique_ptr< dns_pointer > > map;
};
void
dns_iptracker_init();
bool
dns_iptracker_setup_dotLokiLookup(dotLokiLookup *dll,
llarp::huint32_t tunGatewayIp);
bool
dns_iptracker_setup(dns_iptracker *iptracker, llarp::huint32_t tunGatewayIp);
struct dns_pointer *
dns_iptracker_get_free();
struct dns_pointer *
dns_iptracker_get_free(dns_iptracker *iptracker);
#endif

@ -178,7 +178,7 @@ namespace llarp
if(isV6)
{
rec.rr_type = qTypeAAAA;
ip.SIIT(rec.rData);
ip.ToV6(rec.rData);
}
else
{

@ -65,6 +65,12 @@ namespace llarp
return qname.substr(0, qname.find_last_of('.'));
}
bool
Question::HasTLD(const std::string& tld) const
{
return qname.rfind(tld) == (qname.size() - tld.size()) - 1;
}
std::ostream&
Question::print(std::ostream& stream, int level, int spaces) const
{

@ -44,6 +44,10 @@ namespace llarp
/// return qname with no trailing .
std::string
Name() const;
/// determine if we are using this TLD
bool
HasTLD(const std::string& tld) const;
};
inline std::ostream&

@ -15,7 +15,9 @@ namespace llarp
/// handler of dns query hooking
struct IQueryHandler
{
virtual ~IQueryHandler(){}
virtual ~IQueryHandler()
{
}
/// return true if we should hook this message
virtual bool

@ -337,8 +337,9 @@ llarp_epoll_loop::tick(int ms)
{
epoll_event events[1024];
int result;
result = epoll_wait(epollfd, events, 1024, ms);
bool didIO = false;
result = epoll_wait(epollfd, events, 1024, ms);
bool didRead = false;
bool didWrite = false;
if(result > 0)
{
int idx = 0;
@ -362,6 +363,7 @@ llarp_epoll_loop::tick(int ms)
// write THEN READ don't revert me
if(events[idx].events & EPOLLOUT)
{
didWrite = true;
IO([&]() -> ssize_t {
llarp::LogDebug("epoll out");
ev->flush_write();
@ -370,12 +372,11 @@ llarp_epoll_loop::tick(int ms)
}
if(events[idx].events & EPOLLIN)
{
ssize_t amount = IO([&]() -> ssize_t {
didRead = true;
IO([&]() -> ssize_t {
llarp::LogDebug("epoll in");
return ev->read(readbuf, sizeof(readbuf));
});
if(amount > 0)
didIO = true;
}
}
}
@ -385,7 +386,7 @@ llarp_epoll_loop::tick(int ms)
if(result != -1)
tick_listeners();
/// if we didn't get an io events we sleep to avoid 100% cpu use
if(!didIO)
if(didWrite && !didRead)
std::this_thread::sleep_for(std::chrono::milliseconds(5));
return result;
}

@ -52,9 +52,9 @@ namespace llarp
private:
AbstractRouter *m_Router;
std::unordered_map< std::string,
std::unique_ptr< llarp::handlers::ExitEndpoint > >
std::shared_ptr< llarp::handlers::ExitEndpoint > >
m_Exits;
std::list< std::unique_ptr< llarp::handlers::ExitEndpoint > > m_Closed;
std::list< std::shared_ptr< llarp::handlers::ExitEndpoint > > m_Closed;
};
} // namespace exit
} // namespace llarp

@ -190,7 +190,7 @@ namespace llarp
return sent;
}
llarp::path::IHopHandler*
llarp::path::HopHandler_ptr
Endpoint::GetCurrentPath() const
{
auto router = m_Parent->GetRouter();

@ -70,7 +70,7 @@ namespace llarp
bool
UpdateLocalPath(const llarp::PathID_t& nextPath);
llarp::path::IHopHandler*
llarp::path::HopHandler_ptr
GetCurrentPath() const;
const llarp::PubKey&

@ -25,9 +25,9 @@ namespace llarp
{
}
void
BaseSession::HandlePathDied(path::Path*)
void BaseSession::HandlePathDied(path::Path_ptr)
{
BuildOne();
}
util::StatusObject
@ -49,18 +49,12 @@ namespace llarp
bool
BaseSession::ShouldBuildMore(llarp_time_t now) const
{
if(!path::Builder::ShouldBuildMore(now))
return false;
const size_t expect = (1 + (m_NumPaths / 2));
// check 30 seconds into the future and see if we need more paths
const llarp_time_t future = now + (30 * 1000);
if(NumPathsExistingAt(future) < expect)
return llarp::randint() % 4
== 0; // 25% chance for build if we will run out soon
// if we don't have the expended number of paths right now try building
// some if the cooldown timer isn't hit
if(AvailablePaths(llarp::path::ePathRoleExit) < expect)
return !path::Builder::BuildCooldownHit(now);
// maintain regular number of paths
return path::Builder::ShouldBuildMore(now);
const llarp_time_t future = now + (30 * 1000) + buildIntervalLimit;
return NumPathsExistingAt(future) < expect;
}
bool
@ -70,7 +64,10 @@ namespace llarp
{
if(hop == numHops - 1)
{
return db->Get(m_ExitRouter, cur);
if(db->Get(m_ExitRouter, cur))
return true;
router->LookupRouter(m_ExitRouter);
return false;
}
else if(hop == numHops - 2)
{
@ -82,13 +79,13 @@ namespace llarp
}
bool
BaseSession::CheckPathDead(path::Path*, llarp_time_t dlt)
BaseSession::CheckPathDead(path::Path_ptr, llarp_time_t dlt)
{
return dlt >= 10000;
}
void
BaseSession::HandlePathBuilt(llarp::path::Path* p)
BaseSession::HandlePathBuilt(llarp::path::Path_ptr p)
{
path::Builder::HandlePathBuilt(p);
p->SetDropHandler(std::bind(&BaseSession::HandleTrafficDrop, this,
@ -126,13 +123,14 @@ namespace llarp
}
bool
BaseSession::HandleGotExit(llarp::path::Path* p, llarp_time_t b)
BaseSession::HandleGotExit(llarp::path::Path_ptr p, llarp_time_t b)
{
m_LastUse = router->Now();
if(b == 0)
{
llarp::LogInfo("obtained an exit via ", p->Endpoint());
if(IsReady())
CallPendingCallbacks(true);
}
return true;
}
@ -141,8 +139,9 @@ namespace llarp
{
if(success)
{
auto self = shared_from_this();
for(auto& f : m_PendingCallbacks)
f(this);
f(self);
}
else
{
@ -156,7 +155,7 @@ namespace llarp
BaseSession::Stop()
{
CallPendingCallbacks(false);
auto sendExitClose = [&](llarp::path::Path* p) {
auto sendExitClose = [&](const llarp::path::Path_ptr p) {
if(p->SupportsAnyRoles(llarp::path::ePathRoleExit))
{
llarp::LogInfo(p->Name(), " closing exit path");
@ -167,14 +166,14 @@ namespace llarp
}
};
ForEachPath(sendExitClose);
router->pathContext().RemovePathSet(shared_from_this());
return llarp::path::Builder::Stop();
}
bool
BaseSession::HandleTraffic(llarp::path::Path* p, const llarp_buffer_t& buf,
BaseSession::HandleTraffic(llarp::path::Path_ptr, const llarp_buffer_t& buf,
uint64_t counter)
{
(void)p;
if(m_WritePacket)
{
llarp::net::IPv4Packet pkt;
@ -189,10 +188,9 @@ namespace llarp
}
bool
BaseSession::HandleTrafficDrop(llarp::path::Path* p, const PathID_t& path,
BaseSession::HandleTrafficDrop(llarp::path::Path_ptr, const PathID_t& path,
uint64_t s)
{
(void)p;
llarp::LogError("dropped traffic on exit ", m_ExitRouter, " S=", s,
" P=", path);
return true;
@ -237,7 +235,7 @@ namespace llarp
}
bool
BaseSession::Flush()
BaseSession::FlushUpstream()
{
auto now = router->Now();
auto path = PickRandomEstablishedPath(llarp::path::ePathRoleExit);
@ -265,13 +263,18 @@ namespace llarp
item.second.clear();
m_Upstream.clear();
}
return true;
}
void
BaseSession::FlushDownstream()
{
while(m_Downstream.size())
{
if(m_WritePacket)
m_WritePacket(m_Downstream.top().second.ConstBuffer());
m_Downstream.pop();
}
return true;
}
SNodeSession::SNodeSession(

@ -15,10 +15,13 @@ namespace llarp
{
struct BaseSession;
using SessionReadyFunc = std::function< void(BaseSession*) >;
using BaseSession_ptr = std::shared_ptr< BaseSession >;
using SessionReadyFunc = std::function< void(BaseSession_ptr) >;
/// a persisting exit session with an exit router
struct BaseSession : public llarp::path::Builder
struct BaseSession : public llarp::path::Builder,
public std::enable_shared_from_this< BaseSession >
{
static constexpr size_t MaxUpstreamQueueLength = 256;
static constexpr llarp_time_t LifeSpan = 60 * 10 * 1000;
@ -29,6 +32,12 @@ namespace llarp
virtual ~BaseSession();
std::shared_ptr< path::PathSet >
GetSelf() override
{
return shared_from_this();
}
util::StatusObject
ExtractStatus() const;
@ -40,10 +49,10 @@ namespace llarp
}
void
HandlePathDied(llarp::path::Path* p) override;
HandlePathDied(llarp::path::Path_ptr p) override;
bool
CheckPathDead(path::Path* p, llarp_time_t dlt);
CheckPathDead(path::Path_ptr p, llarp_time_t dlt);
bool
SelectHop(llarp_nodedb* db, const RouterContact& prev, RouterContact& cur,
@ -53,14 +62,18 @@ namespace llarp
ShouldBuildMore(llarp_time_t now) const override;
void
HandlePathBuilt(llarp::path::Path* p) override;
HandlePathBuilt(llarp::path::Path_ptr p) override;
bool
QueueUpstreamTraffic(llarp::net::IPv4Packet pkt, const size_t packSize);
/// flush upstream and downstream traffic
/// flush upstream to exit via paths
bool
Flush();
FlushUpstream();
/// flush downstream to user via tun
void
FlushDownstream();
path::PathRole
GetRoles() const override
@ -99,14 +112,14 @@ namespace llarp
PopulateRequest(llarp::routing::ObtainExitMessage& msg) const = 0;
bool
HandleTrafficDrop(llarp::path::Path* p, const llarp::PathID_t& path,
HandleTrafficDrop(llarp::path::Path_ptr p, const llarp::PathID_t& path,
uint64_t s);
bool
HandleGotExit(llarp::path::Path* p, llarp_time_t b);
HandleGotExit(llarp::path::Path_ptr p, llarp_time_t b);
bool
HandleTraffic(llarp::path::Path* p, const llarp_buffer_t& buf,
HandleTraffic(llarp::path::Path_ptr p, const llarp_buffer_t& buf,
uint64_t seqno);
private:

@ -73,14 +73,12 @@ namespace llarp
|| msg.questions[0].qtype == dns::qTypeCNAME
|| msg.questions[0].qtype == dns::qTypeAAAA)
{
if(msg.questions[0].IsName("localhost.loki")
|| msg.questions[0].IsName("random.snode"))
if(msg.questions[0].IsName("localhost.loki"))
return true;
if(msg.questions[0].HasTLD(".snode"))
return true;
service::Address addr;
return addr.FromString(msg.questions[0].Name(), ".snode");
}
else
return false;
return false;
}
bool
@ -247,14 +245,17 @@ namespace llarp
auto itr = m_SNodeSessions.begin();
while(itr != m_SNodeSessions.end())
{
if(!itr->second->Flush())
// TODO: move flush upstream to router event loop
if(!itr->second->FlushUpstream())
{
LogWarn("failed to flush snode traffic to ", itr->first,
" via outbound session");
}
itr->second->FlushDownstream();
++itr;
}
}
m_Router->PumpLL();
}
bool
@ -547,14 +548,13 @@ namespace llarp
huint32_t ip = GetIPForIdent(pubKey);
if(m_SNodeKeys.emplace(pubKey).second)
{
// this is a new service node make an outbound session to them
m_SNodeSessions.emplace(
auto session = std::make_shared< exit::SNodeSession >(
other,
std::unique_ptr< exit::SNodeSession >(new exit::SNodeSession(
other,
std::bind(&ExitEndpoint::QueueSNodePacket, this,
std::placeholders::_1, ip),
GetRouter(), 2, 1, true)));
std::bind(&ExitEndpoint::QueueSNodePacket, this,
std::placeholders::_1, ip),
GetRouter(), 2, 1, true);
// this is a new service node make an outbound session to them
m_SNodeSessions.emplace(other, session);
}
return ip;
}
@ -620,7 +620,10 @@ namespace llarp
if(itr->second->IsExpired(now))
itr = m_SNodeSessions.erase(itr);
else
{
itr->second->Tick(now);
++itr;
}
}
}
{

@ -147,7 +147,7 @@ namespace llarp
SNodes_t m_SNodeKeys;
using SNodeSessions_t =
std::unordered_map< RouterID, std::unique_ptr< exit::SNodeSession >,
std::unordered_map< RouterID, std::shared_ptr< exit::SNodeSession >,
RouterID::Hash >;
/// snode sessions we are talking to directly
SNodeSessions_t m_SNodeSessions;

@ -7,7 +7,9 @@ namespace llarp
{
namespace handlers
{
struct NullEndpoint final : public llarp::service::Endpoint
struct NullEndpoint final
: public llarp::service::Endpoint,
public std::enable_shared_from_this< NullEndpoint >
{
NullEndpoint(const std::string &name, AbstractRouter *r,
llarp::service::Context *parent)
@ -22,6 +24,12 @@ namespace llarp
return true;
}
path::PathSet_ptr
GetSelf() override
{
return shared_from_this();
}
huint32_t
ObtainIPForAddr(const AlignedBuffer< 32 > &, bool) override
{

@ -12,6 +12,7 @@
#include <ev/ev.hpp>
#include <router/abstractrouter.hpp>
#include <service/context.hpp>
#include <util/logic.hpp>
namespace llarp
{
@ -102,11 +103,11 @@ namespace llarp
llarp::LogError(Name(), " bad exit router key: ", v);
return false;
}
m_Exit.reset(new llarp::exit::ExitSession(
m_Exit = std::make_shared< llarp::exit::ExitSession >(
exitRouter,
std::bind(&TunEndpoint::QueueInboundPacketForExit, this,
std::placeholders::_1),
router, m_NumPaths, numHops));
router, m_NumPaths, numHops);
llarp::LogInfo(Name(), " using exit at ", exitRouter);
}
if(k == "local-dns")
@ -227,7 +228,19 @@ namespace llarp
void
TunEndpoint::Flush()
{
auto self = shared_from_this();
FlushSend();
if(m_Exit)
{
RouterLogic()->queue_func([=] {
self->m_Exit->FlushUpstream();
self->Router()->PumpLL();
});
}
RouterLogic()->queue_func([=]() {
self->Pump(self->Now());
self->Router()->PumpLL();
});
}
static bool
@ -280,7 +293,7 @@ namespace llarp
size_t counter = 0;
context->ForEachService(
[&](const std::string &,
const std::unique_ptr< service::Endpoint > &service) -> bool {
const std::shared_ptr< service::Endpoint > &service) -> bool {
service::Address addr = service->GetIdentity().pub.Addr();
msg.AddCNAMEReply(addr.ToString(), 1);
++counter;
@ -312,7 +325,7 @@ namespace llarp
size_t counter = 0;
context->ForEachService(
[&](const std::string &,
const std::unique_ptr< service::Endpoint > &service) -> bool {
const std::shared_ptr< service::Endpoint > &service) -> bool {
huint32_t ip = service->GetIfAddr();
if(ip.h)
{
@ -348,13 +361,12 @@ namespace llarp
{
dns::Message *replyMsg = new dns::Message(std::move(msg));
EnsurePathToSNode(
addr.as_array(), [=](const RouterID &, exit::BaseSession * s) {
addr.as_array(), [=](const RouterID &, exit::BaseSession_ptr s) {
SendDNSReply(addr, s, replyMsg, reply, true, isV6);
});
return true;
}
else
// forward dns
msg.AddNXReply();
reply(msg);
@ -403,18 +415,11 @@ namespace llarp
llarp::service::Address addr;
if(msg.questions.size() == 1)
{
// hook random.snode
if(msg.questions[0].IsName("random.snode"))
/// hook every .loki
if(msg.questions[0].HasTLD(".loki"))
return true;
// hook localhost.loki
if(msg.questions[0].IsName("localhost.loki"))
return true;
const std::string name = msg.questions[0].Name();
// hook .loki
if(addr.FromString(name, ".loki"))
return true;
// hook .snode
if(addr.FromString(name, ".snode"))
/// hook every .snode
if(msg.questions[0].HasTLD(".snode"))
return true;
// hook any ranges we own
if(msg.questions[0].qtype == llarp::dns::qTypePTR)
@ -535,9 +540,23 @@ namespace llarp
llarp::LogInfo(Name(), " allocated up to ", m_MaxIP, " on range ",
m_OurRange);
MapAddress(m_Identity.pub.Addr(), m_OurIP, IsSNode());
if(m_OnUp)
{
m_OnUp->NotifyAsync(NotifyParams());
}
return true;
}
std::unordered_map< std::string, std::string >
TunEndpoint::NotifyParams() const
{
auto env = Endpoint::NotifyParams();
env.emplace("IP_ADDR", m_OurIP.ToString());
env.emplace("IF_ADDR", m_OurRange.ToString());
env.emplace("IF_NAME", tunif.ifname);
return env;
}
bool
TunEndpoint::SetupNetworking()
{
@ -562,7 +581,10 @@ namespace llarp
// call tun code in endpoint logic in case of network isolation
// EndpointLogic()->queue_job({this, handleTickTun});
if(m_Exit)
{
EnsureRouterIsKnown(m_Exit->Endpoint());
m_Exit->Tick(now);
}
Endpoint::Tick(now);
}
@ -755,9 +777,9 @@ namespace llarp
self->FlushSend();
// flush exit traffic queues if it's there
if(self->m_Exit)
self->m_Exit->Flush();
// flush snode traffic
self->FlushSNodeTraffic();
{
self->m_Exit->FlushDownstream();
}
// flush network to user
self->m_NetworkToUserPktQueue.Process([tun](net::IPv4Packet &pkt) {
if(!llarp_ev_tun_async_write(tun, pkt.Buffer()))

@ -20,12 +20,20 @@ namespace llarp
static const char DefaultTunDstAddr[] = "10.10.0.1";
static const char DefaultTunSrcAddr[] = "10.10.0.2";
struct TunEndpoint : public service::Endpoint, public dns::IQueryHandler
struct TunEndpoint : public service::Endpoint,
public dns::IQueryHandler,
public std::enable_shared_from_this< TunEndpoint >
{
TunEndpoint(const std::string& nickname, AbstractRouter* r,
llarp::service::Context* parent);
~TunEndpoint();
path::PathSet_ptr
GetSelf() override
{
return shared_from_this();
}
virtual bool
SetOption(const std::string& k, const std::string& v) override;
@ -35,6 +43,9 @@ namespace llarp
util::StatusObject
ExtractStatus() const;
std::unordered_map< std::string, std::string >
NotifyParams() const override;
bool
ShouldHookDNSMessage(const dns::Message& msg) const override;
@ -195,7 +206,7 @@ namespace llarp
template < typename Addr_t, typename Endpoint_t >
void
SendDNSReply(Addr_t addr, Endpoint_t* ctx, dns::Message* query,
SendDNSReply(Addr_t addr, Endpoint_t ctx, dns::Message* query,
std::function< void(dns::Message) > reply, bool snode,
bool sendIPv6)
{

@ -0,0 +1,31 @@
#ifndef LLARP_HOOK_IHOOK_HPP
#define LLARP_HOOK_IHOOK_HPP
#include <string>
#include <unordered_map>
#include <memory>
namespace llarp
{
namespace hooks
{
/// base type for event hook handlers
struct IBackend
{
~IBackend(){};
virtual void
NotifyAsync(std::unordered_map< std::string, std::string > params) = 0;
/// start backend
virtual bool
Start() = 0;
/// stop backend
virtual bool
Stop() = 0;
};
using Backend_ptr = std::unique_ptr< IBackend >;
} // namespace hooks
} // namespace llarp
#endif

@ -0,0 +1,148 @@
#include <hook/shell.hpp>
#if defined(_WIN32)
/** put win32 stuff here */
#else
#include <util/threadpool.h>
#include <util/logger.hpp>
#include <sys/wait.h>
#include <unistd.h>
#endif
#if defined(Darwin)
#include <crt_externs.h>
#endif
namespace llarp
{
namespace hooks
{
#if defined(_WIN32)
Backend_ptr
ExecShellBackend(std::string)
{
return nullptr;
}
#else
struct ExecShellHookJob
{
const std::string &m_File;
const std::unordered_map< std::string, std::string > m_env;
ExecShellHookJob(
const std::string &f,
const std::unordered_map< std::string, std::string > _env)
: m_File(f), m_env(std::move(_env))
{
}
static void
Exec(void *user)
{
ExecShellHookJob *self = static_cast< ExecShellHookJob * >(user);
std::vector< std::string > _args;
std::vector< char * > args;
std::istringstream s(self->m_File);
for(std::string arg; std::getline(s, arg, ' ');)
{
_args.emplace_back(std::move(arg));
char *ptr = (char *)_args.back().c_str();
args.push_back(ptr);
}
args.push_back(0);
std::vector< std::string > _env(self->m_env.size() + 1);
std::vector< char * > env;
// copy environ
#if defined(Darwin)
char **ptr = *_NSGetEnviron();
#else
char **ptr = environ;
#endif
do
{
env.emplace_back(*ptr);
++ptr;
} while(ptr && *ptr);
// put in our variables
for(const auto &item : self->m_env)
{
_env.emplace_back(item.first + "=" + item.second);
char *ptr = (char *)_env.back().c_str();
env.push_back(ptr);
}
env.push_back(0);
const auto exe = _args[0].c_str();
const auto argv = args.data();
const auto argp = env.data();
pid_t child_process = ::fork();
if(child_process == -1)
{
LogError("failed to fork");
delete self;
return;
}
if(child_process)
{
int status = 0;
::waitpid(child_process, &status, 0);
LogInfo(_args[0], " exit code: ", status);
delete self;
}
else if(::execve(exe, argv, argp) == -1)
{
LogError("failed to exec ", _args[0], " : ", strerror(errno));
}
}
};
struct ExecShellHookBackend : public IBackend
{
llarp_threadpool *m_ThreadPool;
const std::string m_ScriptFile;
ExecShellHookBackend(std::string script)
: m_ThreadPool(llarp_init_threadpool(1, script.c_str()))
, m_ScriptFile(std::move(script))
{
}
~ExecShellHookBackend()
{
llarp_threadpool_stop(m_ThreadPool);
llarp_free_threadpool(&m_ThreadPool);
}
bool
Start() override
{
llarp_threadpool_start(m_ThreadPool);
return true;
}
bool
Stop() override
{
llarp_threadpool_stop(m_ThreadPool);
return true;
}
void
NotifyAsync(
std::unordered_map< std::string, std::string > params) override
{
ExecShellHookJob *job =
new ExecShellHookJob(m_ScriptFile, std::move(params));
llarp_threadpool_queue_job(m_ThreadPool,
{job, &ExecShellHookJob::Exec});
}
};
Backend_ptr
ExecShellBackend(std::string execFilePath)
{
Backend_ptr ptr = std::make_unique< ExecShellHookBackend >(execFilePath);
if(!ptr->Start())
return nullptr;
return ptr;
}
#endif
} // namespace hooks
} // namespace llarp

@ -0,0 +1,15 @@
#ifndef LLARP_HOOK_SHELL_HPP
#define LLARP_HOOK_SHELL_HPP
#include "ihook.hpp"
namespace llarp
{
namespace hooks
{
/// exec file based hook notifier
Backend_ptr
ExecShellBackend(std::string execFilePath);
} // namespace hooks
} // namespace llarp
#endif

@ -24,14 +24,11 @@ namespace llarp
LR_CommitMessage c;
DiscardMessage x;
msg_holder_t() = default;
msg_holder_t() = default;
};
InboundMessageParser::InboundMessageParser(AbstractRouter* _router)
: router(_router)
, from(nullptr)
, msg(nullptr)
, holder(new msg_holder_t())
: router(_router), from(nullptr), msg(nullptr), holder(new msg_holder_t())
{
}

@ -45,7 +45,7 @@ namespace llarp
ILinkMessage* msg;
struct msg_holder_t;
msg_holder_t *holder;
msg_holder_t* holder;
};
} // namespace llarp
#endif

@ -184,7 +184,8 @@ namespace llarp
typedef llarp::path::PathContext Context;
typedef llarp::path::TransitHop Hop;
typedef AsyncFrameDecrypter< LRCMFrameDecrypt > Decrypter;
std::unique_ptr< Decrypter > decrypter;
using Decrypter_ptr = std::unique_ptr< Decrypter >;
Decrypter_ptr decrypter;
std::array< EncryptedFrame, 8 > frames;
Context* context;
// decrypted record
@ -192,9 +193,9 @@ namespace llarp
// the actual hop
std::shared_ptr< Hop > hop;
LRCMFrameDecrypt(Context* ctx, Decrypter* dec,
LRCMFrameDecrypt(Context* ctx, Decrypter_ptr dec,
const LR_CommitMessage* commit)
: decrypter(dec)
: decrypter(std::move(dec))
, frames(commit->frames)
, context(ctx)
, hop(std::make_shared< Hop >())
@ -208,16 +209,15 @@ namespace llarp
/// this is done from logic thread
static void
SendLRCM(void* user)
SendLRCM(std::shared_ptr< LRCMFrameDecrypt > self)
{
std::shared_ptr< LRCMFrameDecrypt > self(
static_cast< LRCMFrameDecrypt* >(user));
if(!self->context->Router()->ConnectionToRouterAllowed(
self->hop->info.upstream))
{
// we are not allowed to forward it ... now what?
llarp::LogError("path to ", self->hop->info.upstream,
"not allowed, dropping build request on the floor");
self->hop = nullptr;
return;
}
// persist sessions to upstream and downstream routers until the commit
@ -237,21 +237,19 @@ namespace llarp
// ... and it's valid
const auto now = self->context->Router()->Now();
if(self->record.nextRC->IsPublicRouter()
&& self->record.nextRC->Verify(self->context->Crypto(), now))
&& self->record.nextRC->Verify(self->context->crypto(), now))
{
llarp_nodedb* n = self->context->Router()->nodedb();
const RouterContact rc = std::move(*self->record.nextRC);
const RouterContact rc = *self->record.nextRC;
// store it into netdb if we don't have it
if(!n->Has(rc.pubkey))
{
static std::function< void(std::shared_ptr< LRCMFrameDecrypt >) > cb =
[](std::shared_ptr< LRCMFrameDecrypt > ctx) {
ctx->context->ForwardLRCM(ctx->hop->info.upstream,
ctx->frames);
ctx->hop = nullptr;
};
llarp::Logic* logic = self->context->Router()->logic();
n->InsertAsync(rc, logic, std::bind(cb, self));
n->InsertAsync(rc, logic, [=]() {
self->context->ForwardLRCM(self->hop->info.upstream,
self->frames);
self->hop = nullptr;
});
return;
}
}
@ -264,17 +262,15 @@ namespace llarp
// this is called from the logic thread
static void
SendPathConfirm(void* user)
SendPathConfirm(std::shared_ptr< LRCMFrameDecrypt > self)
{
std::unique_ptr< LRCMFrameDecrypt > self(
static_cast< LRCMFrameDecrypt* >(user));
// persist session to downstream until path expiration
self->context->Router()->PersistSessionUntil(
self->hop->info.downstream, self->hop->ExpireTime() + 10000);
// put hop
self->context->PutTransitHop(self->hop);
// send path confirmation
llarp::routing::PathConfirmMessage confirm(self->hop->lifetime);
const llarp::routing::PathConfirmMessage confirm(self->hop->lifetime);
if(!self->hop->SendRoutingMessage(confirm, self->context->Router()))
{
llarp::LogError("failed to send path confirmation for ",
@ -284,14 +280,15 @@ namespace llarp
}
static void
HandleDecrypted(llarp_buffer_t* buf, LRCMFrameDecrypt* self)
HandleDecrypted(llarp_buffer_t* buf,
std::shared_ptr< LRCMFrameDecrypt > self)
{
auto now = self->context->Router()->Now();
auto& info = self->hop->info;
if(!buf)
{
llarp::LogError("LRCM decrypt failed from ", info.downstream);
delete self;
self->decrypter = nullptr;
return;
}
buf->cur = buf->base + EncryptedFrameOverheadSize;
@ -300,7 +297,7 @@ namespace llarp
if(!self->record.BDecode(buf))
{
llarp::LogError("malformed frame inside LRCM from ", info.downstream);
delete self;
self->decrypter = nullptr;
return;
}
@ -310,17 +307,17 @@ namespace llarp
if(self->context->HasTransitHop(info))
{
llarp::LogError("duplicate transit hop ", info);
delete self;
self->decrypter = nullptr;
return;
}
// generate path key as we are in a worker thread
auto crypto = self->context->Crypto();
auto crypto = self->context->crypto();
if(!crypto->dh_server(self->hop->pathKey, self->record.commkey,
self->context->EncryptionSecretKey(),
self->record.tunnelNonce))
{
llarp::LogError("LRCM DH Failed ", info);
delete self;
self->decrypter = nullptr;
return;
}
// generate hash of hop key for nonce mutation
@ -366,13 +363,19 @@ namespace llarp
// we are the farthest hop
llarp::LogDebug("We are the farthest hop for ", info);
// send a LRAM down the path
self->context->logic()->queue_job({self, &SendPathConfirm});
self->context->logic()->queue_func([=]() {
SendPathConfirm(self);
self->decrypter = nullptr;
});
}
else
{
// forward upstream
// we are still in the worker thread so post job to logic
self->context->logic()->queue_job({self, &SendLRCM});
self->context->logic()->queue_func([=]() {
SendLRCM(self);
self->decrypter = nullptr;
});
}
}
};
@ -380,16 +383,16 @@ namespace llarp
bool
LR_CommitMessage::AsyncDecrypt(llarp::path::PathContext* context) const
{
LRCMFrameDecrypt::Decrypter* decrypter = new LRCMFrameDecrypt::Decrypter(
context->Crypto(), context->EncryptionSecretKey(),
auto decrypter = std::make_unique< LRCMFrameDecrypt::Decrypter >(
context->crypto(), context->EncryptionSecretKey(),
&LRCMFrameDecrypt::HandleDecrypted);
// copy frames so we own them
LRCMFrameDecrypt* frameDecrypt =
new LRCMFrameDecrypt(context, decrypter, this);
auto frameDecrypt = std::make_shared< LRCMFrameDecrypt >(
context, std::move(decrypter), this);
// decrypt frames async
decrypter->AsyncDecrypt(context->Worker(), frameDecrypt->frames[0],
frameDecrypt);
frameDecrypt->decrypter->AsyncDecrypt(
context->Worker(), frameDecrypt->frames[0], frameDecrypt);
return true;
}
} // namespace llarp

@ -49,6 +49,11 @@ namespace llarp
{
std::array< EncryptedFrame, 8 > frames;
LR_CommitMessage(const std::array< EncryptedFrame, 8 > &_frames)
: ILinkMessage(), frames(_frames)
{
}
LR_CommitMessage() : ILinkMessage()
{
}

@ -82,6 +82,26 @@ namespace llarp
{
namespace net
{
/// a network layer packet
struct NetPacket
{
virtual ~NetPacket(){};
virtual byte_t
Version() const = 0;
virtual byte_t
IPProto() const = 0;
virtual llarp_buffer_t
Buffer() = 0;
virtual llarp_buffer_t
ConstBuffer() const = 0;
};
/// an IPv4 Packet
/// TODO: make it implement NetPacket
struct IPv4Packet
{
static constexpr size_t MaxSize = 1500;

@ -5,15 +5,12 @@
#include <net/net.h>
#include <net/net.hpp>
#include <util/string_view.hpp>
#include <net/net_int.hpp>
#include <string>
namespace llarp
{
// fwd declr
struct huint32_t;
struct nuint32_t;
// real work
struct Addr
{

@ -1 +1,48 @@
#include <net/net_int.hpp>
namespace llarp
{
template <>
void
huint32_t::ToV6(V6Container& c)
{
c.resize(16);
std::fill(c.begin(), c.end(), 0);
htobe32buf(c.data() + 12, h);
c[11] = 0xff;
c[10] = 0xff;
}
template <>
std::string
huint32_t::ToString() const
{
uint32_t n = htonl(h);
char tmp[INET_ADDRSTRLEN] = {0};
if(!inet_ntop(AF_INET, (void*)&n, tmp, sizeof(tmp)))
return "";
return tmp;
}
template <>
std::string
nuint32_t::ToString() const
{
char tmp[INET_ADDRSTRLEN] = {0};
if(!inet_ntop(AF_INET, (void*)&n, tmp, sizeof(tmp)))
return "";
return tmp;
}
template<>
std::string
huint16_t::ToString() const
{
return std::to_string(h);
}
template<>
std::string
nuint16_t::ToString() const
{
return std::to_string(ntohs(n));
}
} // namespace llarp

@ -17,180 +17,170 @@
#include <stdlib.h> // for itoa
#include <iostream>
#include <util/endian.hpp>
#include <vector>
namespace llarp
{
// clang-format off
struct huint32_t
template < typename UInt_t >
struct huint_t
{
uint32_t h;
constexpr huint32_t
operator &(huint32_t x) const { return huint32_t{uint32_t(h & x.h)}; }
constexpr huint32_t
operator |(huint32_t x) const { return huint32_t{uint32_t(h | x.h)}; }
constexpr huint32_t
operator ^(huint32_t x) const { return huint32_t{uint32_t(h ^ x.h)}; }
UInt_t h;
constexpr huint32_t
operator ~() const { return huint32_t{uint32_t(~h)}; }
constexpr huint_t operator&(huint_t x) const
{
return huint_t{UInt_t(h & x.h)};
}
inline huint32_t operator ++() { ++h; return *this; }
inline huint32_t operator --() { --h; return *this; }
constexpr huint_t
operator|(huint_t x) const
{
return huint_t{UInt_t(h | x.h)};
}
constexpr bool operator <(huint32_t x) const { return h < x.h; }
constexpr bool operator ==(huint32_t x) const { return h == x.h; }
constexpr huint_t
operator^(huint_t x) const
{
return huint_t{UInt_t(h ^ x.h)};
}
friend std::ostream&
operator<<(std::ostream& out, const huint32_t& a)
constexpr huint_t
operator~() const
{
uint32_t n = htonl(a.h);
char tmp[INET_ADDRSTRLEN] = {0};
if(inet_ntop(AF_INET, (void*)&n, tmp, sizeof(tmp)))
{
out << tmp;
}
return out;
return huint_t{UInt_t(~h)};
}
template<typename Container>
void SIIT(Container & c)
inline huint_t
operator++()
{
c.resize(16);
std::fill(c.begin(), c.end(), 0);
htobe32buf(c.data() + 12, h);
c[11] = 0xff;
c[10] = 0xff;
++h;
return *this;
}
std::string ToString() const
inline huint_t
operator--()
{
uint32_t n = htonl(h);
char tmp[INET_ADDRSTRLEN] = {0};
if(!inet_ntop(AF_INET, (void*)&n, tmp, sizeof(tmp)))
return "";
return tmp;
--h;
return *this;
}
constexpr bool
operator<(huint_t x) const
{
return h < x.h;
}
constexpr bool
operator==(huint_t x) const
{
return h == x.h;
}
struct Hash
{
inline size_t
operator ()(huint32_t x) const
operator()(huint_t x) const
{
return std::hash< uint32_t >{}(x.h);
return std::hash< UInt_t >{}(x.h);
}
};
};
struct nuint32_t
{
uint32_t n;
using V6Container = std::vector< uint8_t >;
void
ToV6(V6Container& c);
constexpr nuint32_t
operator &(nuint32_t x) const { return nuint32_t{uint32_t(n & x.n)}; }
constexpr nuint32_t
operator |(nuint32_t x) const { return nuint32_t{uint32_t(n | x.n)}; }
constexpr nuint32_t
operator ^(nuint32_t x) const { return nuint32_t{uint32_t(n ^ x.n)}; }
std::string
ToString() const;
constexpr nuint32_t
operator ~() const { return nuint32_t{uint32_t(~n)}; }
friend std::ostream&
operator<<(std::ostream& out, const huint_t& i)
{
return out << i.ToString();
}
};
inline nuint32_t operator ++() { ++n; return *this; }
inline nuint32_t operator --() { --n; return *this; }
using huint128_t = huint_t< __uint128_t >;
using huint32_t = huint_t< uint32_t >;
using huint16_t = huint_t< uint16_t >;
constexpr bool operator <(nuint32_t x) const { return n < x.n; }
constexpr bool operator ==(nuint32_t x) const { return n == x.n; }
template < typename UInt_t >
struct nuint_t
{
UInt_t n;
friend std::ostream&
operator<<(std::ostream& out, const nuint32_t& a)
constexpr nuint_t operator&(nuint_t x) const
{
char tmp[INET_ADDRSTRLEN] = {0};
if(inet_ntop(AF_INET, (void*)&a.n, tmp, sizeof(tmp)))
{
out << tmp;
}
return out;
return nuint_t{UInt_t(n & x.n)};
}
struct Hash
constexpr nuint_t
operator|(nuint_t x) const
{
inline size_t
operator ()(nuint32_t x) const
{
return std::hash< uint32_t >{}(x.n);
}
};
};
return nuint_t{UInt_t(n | x.n)};
}
struct huint16_t
{
uint16_t h;
constexpr nuint_t
operator^(nuint_t x) const
{
return nuint_t{UInt_t(n ^ x.n)};
}
constexpr huint16_t
operator &(huint16_t x) const { return huint16_t{uint16_t(h & x.h)}; }
constexpr huint16_t
operator |(huint16_t x) const { return huint16_t{uint16_t(h | x.h)}; }
constexpr huint16_t
operator ~() const { return huint16_t{uint16_t(~h)}; }
constexpr nuint_t
operator~() const
{
return nuint_t{UInt_t(~n)};
}
inline huint16_t operator ++() { ++h; return *this; }
inline huint16_t operator --() { --h; return *this; }
inline nuint_t
operator++()
{
++n;
return *this;
}
inline nuint_t
operator--()
{
--n;
return *this;
}
constexpr bool operator <(huint16_t x) const { return h < x.h; }
constexpr bool operator ==(huint16_t x) const { return h == x.h; }
constexpr bool
operator<(nuint_t x) const
{
return n < x.n;
}
friend std::ostream&
operator<<(std::ostream& out, const huint16_t& a)
constexpr bool
operator==(nuint_t x) const
{
return out << a.h;
return n == x.n;
}
struct Hash
{
inline size_t
operator ()(huint16_t x) const
operator()(nuint_t x) const
{
return std::hash< uint16_t >{}(x.h);
return std::hash< UInt_t >{}(x.n);
}
};
};
struct nuint16_t
{
uint16_t n;
constexpr nuint16_t
operator &(nuint16_t x) const { return nuint16_t{uint16_t(n & x.n)}; }
constexpr nuint16_t
operator |(nuint16_t x) const { return nuint16_t{uint16_t(n | x.n)}; }
constexpr nuint16_t
operator ~() const { return nuint16_t{uint16_t(~n)}; }
inline nuint16_t operator ++() { ++n; return *this; }
inline nuint16_t operator --() { --n; return *this; }
using V6Container = std::vector< uint8_t >;
void
ToV6(V6Container& c);
constexpr bool operator <(nuint16_t x) const { return n < x.n; }
constexpr bool operator ==(nuint16_t x) const { return n == x.n; }
std::string
ToString() const;
friend std::ostream&
operator<<(std::ostream& out, const nuint16_t& a)
operator<<(std::ostream& out, const nuint_t& i)
{
return out << ntohs(a.n);
return out << i.ToString();
}
struct Hash
{
inline size_t
operator ()(nuint16_t x) const
{
return std::hash< uint16_t >{}(x.n);
}
};
};
// clang-format on
using nuint128_t = nuint_t< __uint128_t >;
using nuint32_t = nuint_t< uint32_t >;
using nuint16_t = nuint_t< uint16_t >;
static inline nuint32_t
xhtonl(huint32_t x)

@ -16,7 +16,6 @@
typedef SSIZE_T ssize_t;
#endif
/**
* nodedb.hpp
*

@ -58,7 +58,7 @@ namespace llarp
}
Crypto*
PathContext::Crypto()
PathContext::crypto()
{
return m_Router->crypto();
}
@ -87,13 +87,12 @@ namespace llarp
const std::array< EncryptedFrame, 8 >& frames)
{
LogDebug("forwarding LRCM to ", nextHop);
LR_CommitMessage msg;
msg.frames = frames;
const LR_CommitMessage msg(frames);
return m_Router->SendToOrQueue(nextHop, &msg);
}
template < typename Map_t, typename Key_t, typename CheckValue_t,
typename GetFunc_t >
IHopHandler*
HopHandler_ptr
MapGet(Map_t& map, const Key_t& k, CheckValue_t check, GetFunc_t get)
{
util::Lock lock(&map.first);
@ -153,7 +152,7 @@ namespace llarp
}
void
PathContext::AddOwnPath(PathSet* set, Path* path)
PathContext::AddOwnPath(PathSet_ptr set, Path_ptr path)
{
set->AddPath(path);
MapPut(m_OurPaths, path->TXID(), set);
@ -169,16 +168,16 @@ namespace llarp
});
}
IHopHandler*
HopHandler_ptr
PathContext::GetByUpstream(const RouterID& remote, const PathID_t& id)
{
auto own = MapGet(
m_OurPaths, id,
[](ABSL_ATTRIBUTE_UNUSED const PathSet* s) -> bool {
[](const PathSet_ptr) -> bool {
// TODO: is this right?
return true;
},
[remote, id](PathSet* p) -> IHopHandler* {
[remote, id](PathSet_ptr p) -> HopHandler_ptr {
return p->GetByUpstream(remote, id);
});
if(own)
@ -189,8 +188,8 @@ namespace llarp
[remote](const std::shared_ptr< TransitHop >& hop) -> bool {
return hop->info.upstream == remote;
},
[](const std::shared_ptr< TransitHop >& h) -> IHopHandler* {
return h.get();
[](const std::shared_ptr< TransitHop >& h) -> HopHandler_ptr {
return h;
});
}
@ -205,7 +204,7 @@ namespace llarp
return itr->second->info.downstream == otherRouter;
}
IHopHandler*
HopHandler_ptr
PathContext::GetByDownstream(const RouterID& remote, const PathID_t& id)
{
return MapGet(
@ -213,12 +212,12 @@ namespace llarp
[remote](const std::shared_ptr< TransitHop >& hop) -> bool {
return hop->info.downstream == remote;
},
[](const std::shared_ptr< TransitHop >& h) -> IHopHandler* {
return h.get();
[](const std::shared_ptr< TransitHop >& h) -> HopHandler_ptr {
return h;
});
}
PathSet*
PathSet_ptr
PathContext::GetLocalPathSet(const PathID_t& id)
{
auto& map = m_OurPaths;
@ -243,7 +242,7 @@ namespace llarp
return m_Router;
}
IHopHandler*
HopHandler_ptr
PathContext::GetPathForTransfer(const PathID_t& id)
{
RouterID us(OurRouterID());
@ -254,7 +253,7 @@ namespace llarp
for(auto i = range.first; i != range.second; ++i)
{
if(i->second->info.upstream == us)
return i->second.get();
return i->second;
}
}
return nullptr;
@ -270,57 +269,41 @@ namespace llarp
void
PathContext::ExpirePaths(llarp_time_t now)
{
util::Lock lock(&m_TransitPaths.first);
auto& map = m_TransitPaths.second;
auto itr = map.begin();
while(itr != map.end())
{
if(itr->second->Expired(now))
util::Lock lock(&m_TransitPaths.first);
auto& map = m_TransitPaths.second;
auto itr = map.begin();
while(itr != map.end())
{
itr = map.erase(itr);
if(itr->second->Expired(now))
{
itr = map.erase(itr);
}
else
++itr;
}
else
++itr;
}
for(auto& builder : m_PathBuilders)
{
if(builder)
builder->ExpirePaths(now);
}
}
void
PathContext::BuildPaths(llarp_time_t now)
{
for(auto& builder : m_PathBuilders)
{
if(builder->ShouldBuildMore(now))
util::Lock lock(&m_OurPaths.first);
auto& map = m_OurPaths.second;
for(auto& item : map)
{
builder->BuildOne();
item.second->ExpirePaths(now);
}
}
}
void
PathContext::TickPaths(llarp_time_t now)
{
for(auto& builder : m_PathBuilders)
builder->Tick(now, m_Router);
}
routing::IMessageHandler*
routing::MessageHandler_ptr
PathContext::GetHandler(const PathID_t& id)
{
routing::IMessageHandler* h = nullptr;
auto pathset = GetLocalPathSet(id);
routing::MessageHandler_ptr h = nullptr;
auto pathset = GetLocalPathSet(id);
if(pathset)
{
h = pathset->GetPathByID(id);
}
if(h)
return h;
RouterID us(OurRouterID());
const RouterID us(OurRouterID());
auto& map = m_TransitPaths;
{
util::Lock lock(&map.first);
@ -328,40 +311,27 @@ namespace llarp
for(auto i = range.first; i != range.second; ++i)
{
if(i->second->info.upstream == us)
return i->second.get();
return i->second;
}
}
return nullptr;
}
void
PathContext::AddPathBuilder(Builder* ctx)
{
m_PathBuilders.push_back(ctx);
}
void
PathContext::RemovePathSet(PathSet* set)
PathContext::RemovePathSet(PathSet_ptr set)
{
util::Lock lock(&m_OurPaths.first);
auto& map = m_OurPaths.second;
auto itr = map.begin();
while(itr != map.end())
{
if(itr->second == set)
if(itr->second.get() == set.get())
itr = map.erase(itr);
else
++itr;
}
}
void
PathContext::RemovePathBuilder(Builder* ctx)
{
m_PathBuilders.remove(ctx);
RemovePathSet(ctx);
}
std::ostream&
TransitHop::print(std::ostream& stream, int level, int spaces) const
{
@ -468,7 +438,7 @@ namespace llarp
if(st == ePathExpired && _status == ePathBuilding)
{
_status = st;
m_PathSet->HandlePathBuildTimeout(this);
m_PathSet->HandlePathBuildTimeout(shared_from_this());
}
else if(st == ePathBuilding)
{
@ -483,7 +453,7 @@ namespace llarp
{
LogInfo("path ", Name(), " died");
_status = st;
m_PathSet->HandlePathDied(this);
m_PathSet->HandlePathDied(shared_from_this());
}
else if(st == ePathEstablished && _status == ePathTimeout)
{
@ -577,21 +547,10 @@ namespace llarp
SendRoutingMessage(latency, r);
return;
}
if(SupportsAnyRoles(ePathRoleExit | ePathRoleSVC))
{
if(m_LastRecvMessage && now > m_LastRecvMessage
&& now - m_LastRecvMessage > path::alive_timeout)
{
// TODO: send close exit message
// r->routerProfiling().MarkPathFail(this);
// EnterState(ePathTimeout, now);
return;
}
}
if(m_LastRecvMessage && now > m_LastRecvMessage)
{
const auto delay = now - m_LastRecvMessage;
if(m_CheckForDead && m_CheckForDead(this, delay))
if(m_CheckForDead && m_CheckForDead(shared_from_this(), delay))
{
r->routerProfiling().MarkPathFail(this);
EnterState(ePathTimeout, now);
@ -599,7 +558,7 @@ namespace llarp
}
else if(dlt >= path::alive_timeout && m_LastRecvMessage == 0)
{
if(m_CheckForDead && m_CheckForDead(this, dlt))
if(m_CheckForDead && m_CheckForDead(shared_from_this(), dlt))
{
r->routerProfiling().MarkPathFail(this);
EnterState(ePathTimeout, now);
@ -684,12 +643,12 @@ namespace llarp
if(m_UpdateExitTX && msg.T == m_UpdateExitTX)
{
if(m_ExitUpdated)
return m_ExitUpdated(this);
return m_ExitUpdated(shared_from_this());
}
if(m_CloseExitTX && msg.T == m_CloseExitTX)
{
if(m_ExitClosed)
return m_ExitClosed(this);
return m_ExitClosed(shared_from_this());
}
return false;
}
@ -740,7 +699,7 @@ namespace llarp
{
MarkActive(r->Now());
if(m_DropHandler)
return m_DropHandler(this, msg.P, msg.S);
return m_DropHandler(shared_from_this(), msg.P, msg.S);
return true;
}
@ -776,7 +735,7 @@ namespace llarp
Path::HandleHiddenServiceFrame(const service::ProtocolFrame& frame)
{
MarkActive(m_PathSet->Now());
return m_DataHandler && m_DataHandler(this, frame);
return m_DataHandler && m_DataHandler(shared_from_this(), frame);
}
bool
@ -791,7 +750,7 @@ namespace llarp
m_LastLatencyTestID = 0;
EnterState(ePathEstablished, now);
if(m_BuiltHook)
m_BuiltHook(this);
m_BuiltHook(shared_from_this());
m_BuiltHook = nullptr;
LogDebug("path latency is now ", intro.latency, " for ", Name());
return true;
@ -917,9 +876,10 @@ namespace llarp
bool
Path::InformExitResult(llarp_time_t B)
{
auto self = shared_from_this();
bool result = true;
for(const auto& hook : m_ObtainedExitHooks)
result &= hook(this, B);
result &= hook(self, B);
m_ObtainedExitHooks.clear();
return result;
}
@ -931,18 +891,22 @@ namespace llarp
// check if we can handle exit data
if(!SupportsAnyRoles(ePathRoleExit | ePathRoleSVC))
return false;
MarkActive(r->Now());
// handle traffic if we have a handler
if(!m_ExitTrafficHandler)
return false;
bool sent = msg.X.size() > 0;
auto self = shared_from_this();
for(const auto& pkt : msg.X)
{
if(pkt.size() <= 8)
return false;
uint64_t counter = bufbe64toh(pkt.data());
m_ExitTrafficHandler(
this, llarp_buffer_t(pkt.data() + 8, pkt.size() - 8), counter);
if(m_ExitTrafficHandler(
self, llarp_buffer_t(pkt.data() + 8, pkt.size() - 8), counter))
{
MarkActive(r->Now());
EnterState(ePathEstablished, r->Now());
}
}
return sent;
}

@ -151,6 +151,8 @@ namespace llarp
uint64_t m_SequenceNum = 0;
};
using HopHandler_ptr = std::shared_ptr< IHopHandler >;
struct TransitHop : public IHopHandler, public routing::IMessageHandler
{
TransitHop();
@ -303,25 +305,27 @@ namespace llarp
};
/// A path we made
struct Path : public IHopHandler, public routing::IMessageHandler
struct Path : public IHopHandler,
public routing::IMessageHandler,
public std::enable_shared_from_this< Path >
{
using BuildResultHookFunc = std::function< void(Path*) >;
using CheckForDeadFunc = std::function< bool(Path*, llarp_time_t) >;
using BuildResultHookFunc = std::function< void(Path_ptr) >;
using CheckForDeadFunc = std::function< bool(Path_ptr, llarp_time_t) >;
using DropHandlerFunc =
std::function< bool(Path*, const PathID_t&, uint64_t) >;
std::function< bool(Path_ptr, const PathID_t&, uint64_t) >;
using HopList = std::vector< PathHopConfig >;
using DataHandlerFunc =
std::function< bool(Path*, const service::ProtocolFrame&) >;
using ExitUpdatedFunc = std::function< bool(Path*) >;
using ExitClosedFunc = std::function< bool(Path*) >;
std::function< bool(Path_ptr, const service::ProtocolFrame&) >;
using ExitUpdatedFunc = std::function< bool(Path_ptr) >;
using ExitClosedFunc = std::function< bool(Path_ptr) >;
using ExitTrafficHandlerFunc =
std::function< bool(Path*, const llarp_buffer_t&, uint64_t) >;
std::function< bool(Path_ptr, const llarp_buffer_t&, uint64_t) >;
/// (path, backoff) backoff is 0 on success
using ObtainedExitHandler = std::function< bool(Path*, llarp_time_t) >;
using ObtainedExitHandler = std::function< bool(Path_ptr, llarp_time_t) >;
HopList hops;
PathSet* m_PathSet;
PathSet* const m_PathSet;
service::Introduction intro;
@ -579,19 +583,6 @@ namespace llarp
void
ExpirePaths(llarp_time_t now);
/// called from router tick function
/// builds all paths we need to build at current tick
void
BuildPaths(llarp_time_t now);
/// called from router tick function
void
TickPaths(llarp_time_t now);
/// track a path builder with this context
void
AddPathBuilder(Builder* set);
void
AllowTransit();
@ -610,22 +601,22 @@ namespace llarp
void
PutTransitHop(std::shared_ptr< TransitHop > hop);
IHopHandler*
HopHandler_ptr
GetByUpstream(const RouterID& id, const PathID_t& path);
bool
TransitHopPreviousIsRouter(const PathID_t& path, const RouterID& r);
IHopHandler*
HopHandler_ptr
GetPathForTransfer(const PathID_t& topath);
IHopHandler*
HopHandler_ptr
GetByDownstream(const RouterID& id, const PathID_t& path);
PathSet*
PathSet_ptr
GetLocalPathSet(const PathID_t& id);
routing::IMessageHandler*
routing::MessageHandler_ptr
GetHandler(const PathID_t& id);
bool
@ -642,13 +633,10 @@ namespace llarp
HandleLRDM(const RelayDownstreamMessage& msg);
void
AddOwnPath(PathSet* set, Path* p);
void
RemovePathBuilder(Builder* ctx);
AddOwnPath(PathSet_ptr set, Path_ptr p);
void
RemovePathSet(PathSet* set);
RemovePathSet(PathSet_ptr set);
using TransitHopsMap_t =
std::multimap< PathID_t, std::shared_ptr< TransitHop > >;
@ -660,7 +648,7 @@ namespace llarp
};
// maps path id -> pathset owner of path
using OwnedPathsMap_t = std::map< PathID_t, PathSet* >;
using OwnedPathsMap_t = std::map< PathID_t, PathSet_ptr >;
struct SyncOwnedPathsMap_t
{
@ -672,7 +660,7 @@ namespace llarp
Worker();
llarp::Crypto*
Crypto();
crypto();
Logic*
logic();
@ -689,9 +677,7 @@ namespace llarp
private:
AbstractRouter* m_Router;
SyncTransitMap_t m_TransitPaths;
SyncTransitMap_t m_Paths;
SyncOwnedPathsMap_t m_OurPaths;
std::list< Builder* > m_PathBuilders;
bool m_AllowTransit;
};
} // namespace path

@ -15,10 +15,10 @@ namespace llarp
template < typename User >
struct AsyncPathKeyExchangeContext
{
typedef path::Path Path_t;
typedef path::Builder PathSet_t;
PathSet_t* pathset = nullptr;
Path_t* path = nullptr;
typedef path::Path_ptr Path_t;
typedef path::PathSet_ptr PathSet_t;
PathSet_t pathset = nullptr;
Path_t path = nullptr;
typedef std::function< void(AsyncPathKeyExchangeContext< User >*) > Handler;
User* user = nullptr;
@ -32,8 +32,6 @@ namespace llarp
~AsyncPathKeyExchangeContext()
{
if(path)
delete path;
}
static void
@ -81,9 +79,8 @@ namespace llarp
else
{
hop.upstream = ctx->path->hops[ctx->idx].rc.pubkey;
if(ctx->pathset->ShouldBundleRC())
record.nextRC =
std::make_unique< RouterContact >(ctx->path->hops[ctx->idx].rc);
record.nextRC =
std::make_unique< RouterContact >(ctx->path->hops[ctx->idx].rc);
}
// build record
@ -134,7 +131,7 @@ namespace llarp
/// Generate all keys asynchronously and call handler when done
void
AsyncGenerateKeys(Path_t* p, Logic* l, llarp_threadpool* pool, User* u,
AsyncGenerateKeys(Path_t p, Logic* l, llarp_threadpool* pool, User* u,
Handler func)
{
path = p;
@ -164,13 +161,10 @@ namespace llarp
ctx->router->PersistSessionUntil(remote, ctx->path->ExpireTime());
// add own path
ctx->router->pathContext().AddOwnPath(ctx->pathset, ctx->path);
ctx->path = nullptr;
}
else
LogError(ctx->pathset->Name(), " failed to send LRCM to ", remote);
}
// decrement keygen counter
ctx->pathset->keygens--;
}
namespace path
@ -179,22 +173,27 @@ namespace llarp
size_t pathNum, size_t hops)
: path::PathSet(pathNum), router(p_router), dht(p_dht), numHops(hops)
{
p_router->pathContext().AddPathBuilder(this);
p_router->crypto()->encryption_keygen(enckey);
_run.store(true);
keygens.store(0);
}
Builder::~Builder()
{
router->pathContext().RemovePathBuilder(this);
}
void
Builder::Tick(llarp_time_t now)
{
ExpirePaths(now);
if(ShouldBuildMore(now))
BuildOne();
TickPaths(now, router);
}
util::StatusObject
Builder::ExtractStatus() const
{
util::StatusObject obj{{"keygens", uint64_t(keygens.load())},
{"numHops", uint64_t(numHops)},
util::StatusObject obj{{"numHops", uint64_t(numHops)},
{"numPaths", uint64_t(m_NumPaths)}};
std::vector< util::StatusObject > pathObjs;
std::transform(m_Paths.begin(), m_Paths.end(),
@ -259,9 +258,7 @@ namespace llarp
bool
Builder::ShouldRemove() const
{
if(!IsStopped())
return false;
return keygens.load() > 0;
return IsStopped();
}
const SecretKey&
@ -340,30 +337,30 @@ namespace llarp
AsyncPathKeyExchangeContext< Builder >* ctx =
new AsyncPathKeyExchangeContext< Builder >(router->crypto());
ctx->router = router;
ctx->pathset = this;
auto path = new path::Path(hops, this, roles);
path->SetBuildResultHook([this](Path* p) { this->HandlePathBuilt(p); });
++keygens;
ctx->pathset = GetSelf();
auto path = std::make_shared< path::Path >(hops, this, roles);
path->SetBuildResultHook(
[this](Path_ptr p) { this->HandlePathBuilt(p); });
ctx->AsyncGenerateKeys(path, router->logic(), router->threadpool(), this,
&PathBuilderKeysGenerated);
}
void
Builder::HandlePathBuilt(Path* p)
Builder::HandlePathBuilt(Path_ptr p)
{
buildIntervalLimit = MIN_PATH_BUILD_INTERVAL;
router->routerProfiling().MarkPathSuccess(p);
router->routerProfiling().MarkPathSuccess(p.get());
LogInfo(p->Name(), " built latency=", p->intro.latency);
}
void
Builder::HandlePathBuildTimeout(Path* p)
Builder::HandlePathBuildTimeout(Path_ptr p)
{
// linear backoff
static constexpr llarp_time_t MaxBuildInterval = 30 * 1000;
buildIntervalLimit =
std::min(1000 + buildIntervalLimit, MaxBuildInterval);
router->routerProfiling().MarkPathFail(p);
router->routerProfiling().MarkPathFail(p.get());
PathSet::HandlePathBuildTimeout(p);
}

@ -29,9 +29,6 @@ namespace llarp
llarp_time_t lastBuild = 0;
llarp_time_t buildIntervalLimit = MIN_PATH_BUILD_INTERVAL;
// how many keygens are currently happening
std::atomic< uint8_t > keygens;
/// construct
Builder(AbstractRouter* p_router, llarp_dht_context* p_dht,
size_t numPaths, size_t numHops);
@ -75,8 +72,11 @@ namespace llarp
llarp_time_t
Now() const override;
virtual void
Tick(llarp_time_t now) override;
void
BuildOne(PathRole roles = ePathRoleAny);
BuildOne(PathRole roles = ePathRoleAny) override;
void
Build(const std::vector< RouterContact >& hops,
@ -93,11 +93,14 @@ namespace llarp
GetTunnelEncryptionSecretKey() const;
virtual void
HandlePathBuilt(Path* p) override;
HandlePathBuilt(Path_ptr p) override;
virtual void
HandlePathBuildTimeout(Path* p) override;
HandlePathBuildTimeout(Path_ptr p) override;
};
using Builder_ptr = std::shared_ptr< Builder >;
} // namespace path
} // namespace llarp

@ -16,8 +16,11 @@ namespace llarp
PathSet::ShouldBuildMore(llarp_time_t now) const
{
(void)now;
Lock_t l(&m_PathsMutex);
return m_Paths.size() < m_NumPaths;
const auto building = NumInStatus(ePathBuilding);
if(building > m_NumPaths)
return false;
const auto established = NumInStatus(ePathEstablished);
return established <= m_NumPaths;
}
bool
@ -58,7 +61,7 @@ namespace llarp
}
void
PathSet::Tick(llarp_time_t now, AbstractRouter* r)
PathSet::TickPaths(llarp_time_t now, AbstractRouter* r)
{
Lock_t l(&m_PathsMutex);
for(auto& item : m_Paths)
@ -77,20 +80,17 @@ namespace llarp
while(itr != m_Paths.end())
{
if(itr->second->Expired(now))
{
delete itr->second;
itr = m_Paths.erase(itr);
}
else
++itr;
}
}
Path*
Path_ptr
PathSet::GetEstablishedPathClosestTo(RouterID id, PathRole roles) const
{
Lock_t l(&m_PathsMutex);
Path* path = nullptr;
Path_ptr path = nullptr;
AlignedBuffer< 32 > dist;
AlignedBuffer< 32 > to = id;
dist.Fill(0xff);
@ -110,12 +110,12 @@ namespace llarp
return path;
}
Path*
Path_ptr
PathSet::GetNewestPathByRouter(RouterID id, PathRole roles) const
{
Lock_t l(&m_PathsMutex);
Path* chosen = nullptr;
auto itr = m_Paths.begin();
Path_ptr chosen = nullptr;
auto itr = m_Paths.begin();
while(itr != m_Paths.end())
{
if(itr->second->IsReady() && itr->second->SupportsAnyRoles(roles))
@ -133,12 +133,12 @@ namespace llarp
return chosen;
}
Path*
Path_ptr
PathSet::GetPathByRouter(RouterID id, PathRole roles) const
{
Lock_t l(&m_PathsMutex);
Path* chosen = nullptr;
auto itr = m_Paths.begin();
Path_ptr chosen = nullptr;
auto itr = m_Paths.begin();
while(itr != m_Paths.end())
{
if(itr->second->IsReady() && itr->second->SupportsAnyRoles(roles))
@ -156,7 +156,7 @@ namespace llarp
return chosen;
}
Path*
Path_ptr
PathSet::GetByEndpointWithID(RouterID ep, PathID_t id) const
{
Lock_t l(&m_PathsMutex);
@ -172,7 +172,7 @@ namespace llarp
return nullptr;
}
Path*
Path_ptr
PathSet::GetPathByID(PathID_t id) const
{
Lock_t l(&m_PathsMutex);
@ -218,22 +218,22 @@ namespace llarp
}
void
PathSet::AddPath(Path* path)
PathSet::AddPath(Path_ptr path)
{
Lock_t l(&m_PathsMutex);
auto upstream = path->Upstream(); // RouterID
auto RXID = path->RXID(); // PathID
m_Paths.emplace(std::make_pair(upstream, RXID), path);
m_Paths.emplace(std::make_pair(upstream, RXID), std::move(path));
}
void
PathSet::RemovePath(Path* path)
PathSet::RemovePath(Path_ptr path)
{
Lock_t l(&m_PathsMutex);
m_Paths.erase({path->Upstream(), path->RXID()});
}
Path*
Path_ptr
PathSet::GetByUpstream(RouterID remote, PathID_t rxid) const
{
Lock_t l(&m_PathsMutex);
@ -285,7 +285,7 @@ namespace llarp
}
void
PathSet::HandlePathBuildTimeout(Path* p)
PathSet::HandlePathBuildTimeout(Path_ptr p)
{
LogInfo(Name(), " path build ", p->HopsString(), " timed out");
}
@ -310,10 +310,10 @@ namespace llarp
return found;
}
Path*
Path_ptr
PathSet::PickRandomEstablishedPath(PathRole roles) const
{
std::vector< Path* > established;
std::vector< Path_ptr > established;
Lock_t l(&m_PathsMutex);
auto itr = m_Paths.begin();
while(itr != m_Paths.end())

@ -5,7 +5,6 @@
#include <router_id.hpp>
#include <routing/message.hpp>
#include <service/intro_set.hpp>
#include <service/lookup.hpp>
#include <util/status.hpp>
#include <util/threading.hpp>
#include <util/time.hpp>
@ -57,6 +56,12 @@ namespace llarp
// forward declare
struct Path;
using Path_ptr = std::shared_ptr< Path >;
struct PathSet;
using PathSet_ptr = std::shared_ptr< PathSet >;
/// a set of paths owned by an entity
struct PathSet
{
@ -64,34 +69,41 @@ namespace llarp
/// @params numPaths the number of paths to maintain
PathSet(size_t numPaths);
/// get a shared_ptr of ourself
virtual PathSet_ptr
GetSelf() = 0;
virtual void
BuildOne(PathRole roles = ePathRoleAny) = 0;
/// tick owned paths
void
Tick(llarp_time_t now, AbstractRouter* r);
virtual void
Tick(llarp_time_t now) = 0;
/// count the number of paths that will exist at this timestamp in future
size_t
NumPathsExistingAt(llarp_time_t futureTime) const;
void
RemovePath(Path* path);
RemovePath(Path_ptr path);
virtual void
HandlePathBuilt(Path* path) = 0;
HandlePathBuilt(Path_ptr path) = 0;
virtual void
HandlePathBuildTimeout(__attribute__((unused)) Path* path);
HandlePathBuildTimeout(__attribute__((unused)) Path_ptr path);
/// a path died now what?
virtual void
HandlePathDied(Path* path) = 0;
HandlePathDied(Path_ptr path) = 0;
bool
GetNewestIntro(service::Introduction& intro) const;
void
AddPath(Path* path);
AddPath(Path_ptr path);
Path*
Path_ptr
GetByUpstream(RouterID remote, PathID_t rxid) const;
void
@ -167,24 +179,24 @@ namespace llarp
return nullptr;
}
Path*
Path_ptr
GetEstablishedPathClosestTo(RouterID router,
PathRole roles = ePathRoleAny) const;
Path*
Path_ptr
PickRandomEstablishedPath(PathRole roles = ePathRoleAny) const;
Path*
Path_ptr
GetPathByRouter(RouterID router, PathRole roles = ePathRoleAny) const;
Path*
Path_ptr
GetNewestPathByRouter(RouterID router,
PathRole roles = ePathRoleAny) const;
Path*
Path_ptr
GetPathByID(PathID_t id) const;
Path*
Path_ptr
GetByEndpointWithID(RouterID router, PathID_t id) const;
bool
@ -209,19 +221,10 @@ namespace llarp
size_t m_NumPaths;
void
ForEachPath(std::function< void(Path*) > visit)
{
Lock_t lock(&m_PathsMutex);
auto itr = m_Paths.begin();
while(itr != m_Paths.end())
{
visit(itr->second);
++itr;
}
}
TickPaths(llarp_time_t now, AbstractRouter* r);
void
ForEachPath(std::function< void(const Path*) > visit) const
ForEachPath(std::function< void(const Path_ptr&) > visit) const
{
Lock_t lock(&m_PathsMutex);
auto itr = m_Paths.begin();
@ -242,9 +245,10 @@ namespace llarp
return RouterID::Hash()(i.first) ^ PathID_t::Hash()(i.second);
}
};
using Mtx_t = util::NullMutex;
using Lock_t = util::NullLock;
using PathMap_t = std::unordered_map< PathInfo_t, Path*, PathInfoHash >;
using Mtx_t = util::NullMutex;
using Lock_t = util::NullLock;
using PathMap_t =
std::unordered_map< PathInfo_t, Path_ptr, PathInfoHash >;
mutable Mtx_t m_PathsMutex;
PathMap_t m_Paths;
};

@ -96,9 +96,32 @@ namespace llarp
return checkIsGood(pathFailCount, pathSuccessCount, chances);
}
Profiling::Profiling() : IBEncodeMessage()
{
m_DisableProfiling.store(false);
}
Profiling::~Profiling()
{
}
void
Profiling::Disable()
{
m_DisableProfiling.store(true);
}
void
Profiling::Enable()
{
m_DisableProfiling.store(false);
}
bool
Profiling::IsBadForConnect(const RouterID& r, uint64_t chances)
{
if(m_DisableProfiling.load())
return false;
lock_t lock(&m_ProfilesMutex);
auto itr = m_Profiles.find(r);
if(itr == m_Profiles.end())
@ -109,6 +132,8 @@ namespace llarp
bool
Profiling::IsBadForPath(const RouterID& r, uint64_t chances)
{
if(m_DisableProfiling.load())
return false;
lock_t lock(&m_ProfilesMutex);
auto itr = m_Profiles.find(r);
if(itr == m_Profiles.end())
@ -119,6 +144,8 @@ namespace llarp
bool
Profiling::IsBad(const RouterID& r, uint64_t chances)
{
if(m_DisableProfiling.load())
return false;
lock_t lock(&m_ProfilesMutex);
auto itr = m_Profiles.find(r);
if(itr == m_Profiles.end())

@ -53,13 +53,8 @@ namespace llarp
struct Profiling final : public IBEncodeMessage
{
Profiling() : IBEncodeMessage()
{
}
~Profiling()
{
}
Profiling();
~Profiling();
/// generic variant
bool
@ -110,6 +105,12 @@ namespace llarp
bool
ShouldSave(llarp_time_t now) const;
void
Disable();
void
Enable();
private:
bool
BEncodeNoLock(llarp_buffer_t* buf) const
@ -118,6 +119,7 @@ namespace llarp
mutable util::Mutex m_ProfilesMutex; // protects m_Profiles
std::map< RouterID, RouterProfile > m_Profiles GUARDED_BY(m_ProfilesMutex);
llarp_time_t m_LastSave = 0;
std::atomic< bool > m_DisableProfiling;
};
} // namespace llarp

@ -117,6 +117,10 @@ namespace llarp
virtual void
Stop() = 0;
/// pump low level links
virtual void
PumpLL() = 0;
virtual bool
IsBootstrapNode(RouterID r) const = 0;
@ -143,9 +147,14 @@ namespace llarp
virtual void
SessionClosed(RouterID remote) = 0;
/// returns system clock milliseconds since epoch
virtual llarp_time_t
Now() const = 0;
/// returns milliseconds since started
virtual llarp_time_t
Uptime() const = 0;
virtual bool
GetRandomGoodRouter(RouterID &r) = 0;

@ -293,6 +293,19 @@ namespace llarp
return true;
}
void
Router::PumpLL()
{
for(const auto &link : inboundLinks)
{
link->Pump();
}
for(const auto &link : outboundLinks)
{
link->Pump();
}
}
constexpr size_t MaxPendingSendQueueSize = 8;
bool
@ -395,7 +408,7 @@ namespace llarp
void
Router::ForEachPeer(std::function< void(ILinkSession *) > visit)
{
for(const auto &link : inboundLinks)
for(const auto &link : outboundLinks)
{
link->ForEachSession([visit](ILinkSession *peer) { visit(peer); });
}
@ -447,9 +460,12 @@ namespace llarp
}
void
Router::AddInboundLink(std::unique_ptr< ILinkLayer > &link)
Router::AddLink(std::unique_ptr< ILinkLayer > link, bool inbound)
{
inboundLinks.emplace(std::move(link));
if(inbound)
inboundLinks.emplace(std::move(link));
else
outboundLinks.emplace(std::move(link));
}
bool
@ -731,7 +747,8 @@ namespace llarp
llarp::LogDebug(section, " ", key, "=", val);
int af;
uint16_t proto;
uint16_t proto = 0;
std::set< std::string > opts;
if(StrEq(val, "eth"))
{
#ifdef AF_LINK
@ -742,11 +759,39 @@ namespace llarp
#endif
proto = LLARP_ETH_PROTO;
}
else
else if(StrEq(section, "bind"))
{
// try IPv4 first
af = AF_INET;
proto = std::atoi(val);
af = AF_INET;
std::set< std::string > parsed_opts;
std::string v = val;
std::string::size_type idx;
do
{
idx = v.find_first_of(',');
if(idx != std::string::npos)
{
parsed_opts.insert(v.substr(0, idx));
v = v.substr(idx + 1);
}
else
parsed_opts.insert(v);
} while(idx != std::string::npos);
/// for each option
for(const auto &item : parsed_opts)
{
/// see if it's a number
auto port = std::atoi(item.c_str());
if(port > 0)
{
/// set port
if(proto == 0)
proto = port;
} /// otherwise add to opts
else
opts.insert(item);
}
}
if(StrEq(section, "bind"))
@ -765,14 +810,27 @@ namespace llarp
}
if(server->Configure(netloop(), key, af, proto))
{
AddInboundLink(server);
AddLink(std::move(server), true);
return;
}
LogError("failed to bind inbound link on ", key, " port ", val);
LogError("failed to bind inbound link on ", key, " port ", proto);
}
}
else if(StrEq(section, "network"))
{
if(StrEq(key, "profiling"))
{
if(IsTrueValue(val))
{
routerProfiling().Enable();
LogInfo("router profiling explicitly enabled");
}
else if(IsFalseValue(val))
{
routerProfiling().Disable();
LogInfo("router profiling explicitly disabled");
}
}
if(StrEq(key, "profiles"))
{
routerProfilesFile = val;
@ -1073,13 +1131,11 @@ namespace llarp
ServiceNodeLookupRouterWhenExpired(remote);
return;
}
auto ep = hiddenServiceContext().getFirstEndpoint();
if(ep == nullptr)
{
LogError("cannot lookup ", remote, " no service endpoints available");
return;
}
ep->LookupRouterAnon(remote);
_hiddenServiceContext.ForEachService(
[=](const std::string &,
const std::shared_ptr< service::Endpoint > &ep) -> bool {
return !ep->LookupRouterAnon(remote);
});
}
bool
@ -1096,6 +1152,8 @@ namespace llarp
void
Router::Tick()
{
if(_stopping)
return;
// LogDebug("tick router");
auto now = Now();
@ -1129,7 +1187,7 @@ namespace llarp
return !IsBootstrapNode(rc.pubkey);
});
}
paths.TickPaths(now);
// expire transit paths
paths.ExpirePaths(now);
{
@ -1176,20 +1234,18 @@ namespace llarp
else
LogError("we have no bootstrap nodes specified");
}
else
if(connected < minConnectedRouters)
{
if(connected < minConnectedRouters)
{
size_t dlt = minConnectedRouters - connected;
LogInfo("connecting to ", dlt, " random routers to keep alive");
ConnectToRandomRouters(dlt);
}
size_t dlt = minConnectedRouters - connected;
LogInfo("connecting to ", dlt, " random routers to keep alive");
ConnectToRandomRouters(dlt);
}
if(!IsServiceNode())
{
_hiddenServiceContext.Tick(now);
}
paths.BuildPaths(now);
_exitContext.Tick(now);
if(rpcCaller)
rpcCaller->Tick(now);
@ -1569,9 +1625,19 @@ namespace llarp
llarp_dht_context_start(dht(), pubkey());
ScheduleTicker(1000);
_running.store(true);
_startedAt = Now();
return _running;
}
llarp_time_t
Router::Uptime() const
{
const llarp_time_t _now = Now();
if(_startedAt && _now > _startedAt)
return _now - _startedAt;
return 0;
}
static void
RouterAfterStopLinks(void *u, uint64_t, uint64_t)
{
@ -1715,8 +1781,10 @@ namespace llarp
|| self->HasPendingConnectJob(other.pubkey)))
{
if(!self->IsBootstrapNode(other.pubkey))
self->TryConnectAsync(other, 5);
--want;
{
if(self->TryConnectAsync(other, 5))
--want;
}
}
return want > 0;
});
@ -1808,7 +1876,7 @@ namespace llarp
for(const auto &factory : linkFactories)
{
auto link = factory(this);
std::unique_ptr< ILinkLayer > link = factory(this);
if(!link)
continue;
if(!link->EnsureKeys(transport_keyfile.string().c_str()))
@ -1823,7 +1891,7 @@ namespace llarp
{
if(!link->Configure(netloop(), "*", af, m_OutboundPort))
continue;
outboundLinks.insert(std::move(link));
AddLink(std::move(link), false);
break;
}
}

@ -204,6 +204,10 @@ namespace llarp
llarp_threadpool *disk;
llarp_dht_context *_dht = nullptr;
llarp_nodedb *_nodedb;
llarp_time_t _startedAt;
llarp_time_t
Uptime() const override;
bool
Sign(Signature &sig, const llarp_buffer_t &buf) const override;
@ -267,6 +271,9 @@ namespace llarp
return IsTrueValue(itr->second.c_str());
}
void
PumpLL() override;
bool
CreateDefaultHiddenService();
@ -335,7 +342,7 @@ namespace llarp
const llarp_buffer_t &msg) override;
void
AddInboundLink(std::unique_ptr< ILinkLayer > &link);
AddLink(std::unique_ptr< ILinkLayer > link, bool outbound = false);
bool
InitOutboundLinks();

@ -1,6 +1,8 @@
#ifndef LLARP_ROUTING_HANDLER_HPP
#define LLARP_ROUTING_HANDLER_HPP
#include <memory>
namespace llarp
{
struct AbstractRouter;
@ -34,53 +36,56 @@ namespace llarp
{
virtual bool
HandleObtainExitMessage(const ObtainExitMessage& msg,
AbstractRouter *r) = 0;
AbstractRouter* r) = 0;
virtual bool
HandleGrantExitMessage(const GrantExitMessage& msg,
AbstractRouter *r) = 0;
AbstractRouter* r) = 0;
virtual bool
HandleRejectExitMessage(const RejectExitMessage& msg,
AbstractRouter *r) = 0;
AbstractRouter* r) = 0;
virtual bool
HandleTransferTrafficMessage(const TransferTrafficMessage& msg,
AbstractRouter *r) = 0;
AbstractRouter* r) = 0;
virtual bool
HandleUpdateExitMessage(const UpdateExitMessage& msg,
AbstractRouter *r) = 0;
AbstractRouter* r) = 0;
virtual bool
HandleUpdateExitVerifyMessage(const UpdateExitVerifyMessage& msg,
AbstractRouter *r) = 0;
AbstractRouter* r) = 0;
virtual bool
HandleCloseExitMessage(const CloseExitMessage& msg,
AbstractRouter *r) = 0;
AbstractRouter* r) = 0;
virtual bool
HandleDataDiscardMessage(const DataDiscardMessage& msg,
AbstractRouter *r) = 0;
AbstractRouter* r) = 0;
virtual bool
HandlePathTransferMessage(const PathTransferMessage& msg,
AbstractRouter *r) = 0;
AbstractRouter* r) = 0;
virtual bool
HandleHiddenServiceFrame(const service::ProtocolFrame& msg) = 0;
virtual bool
HandlePathConfirmMessage(const PathConfirmMessage& msg,
AbstractRouter *r) = 0;
AbstractRouter* r) = 0;
virtual bool
HandlePathLatencyMessage(const PathLatencyMessage& msg,
AbstractRouter *r) = 0;
AbstractRouter* r) = 0;
virtual bool
HandleDHTMessage(const dht::IMessage& msg, AbstractRouter *r) = 0;
HandleDHTMessage(const dht::IMessage& msg, AbstractRouter* r) = 0;
};
using MessageHandler_ptr = std::shared_ptr< IMessageHandler >;
} // namespace routing
} // namespace llarp

@ -1,6 +1,7 @@
#include <rpc/rpc.hpp>
#include <router/abstractrouter.hpp>
#include <service/context.hpp>
#include <util/logger.hpp>
#include <router_id.hpp>
#include <exit/context.hpp>
@ -206,7 +207,7 @@ namespace llarp
Response
DumpState() const
{
util::StatusObject dump = router->ExtractStatus();
const util::StatusObject dump = router->ExtractStatus();
return dump.get();
}
@ -243,6 +244,32 @@ namespace llarp
return resp;
}
Response
DumpStatus() const
{
size_t numServices = 0;
size_t numServicesReady = 0;
Response services = Response::array();
auto visitor =
[&](const std::string& name,
const std::shared_ptr< service::Endpoint >& ptr) -> bool {
numServices++;
if(ptr->IsReady())
numServicesReady++;
const Response status{{"ready", ptr->IsReady()},
{"stopped", ptr->IsStopped()},
{"stale", ptr->IntrosetIsStale()}};
services.emplace_back(Response{name, status});
return true;
};
router->hiddenServiceContext().ForEachService(visitor);
const Response resp{{"uptime", router->Uptime()},
{"servicesTotal", numServices},
{"servicesReady", numServicesReady},
{"services", services}};
return resp;
}
absl::optional< Response >
HandleJSONRPC(Method_t method,
__attribute__((unused)) const Params& params)
@ -259,6 +286,10 @@ namespace llarp
{
return DumpState();
}
else if(method == "llarp.admin.status")
{
return DumpStatus();
}
return false;
}
};

@ -47,8 +47,8 @@ namespace llarp
void
Context::ForEachService(
std::function< bool(const std::string &,
const std::unique_ptr< Endpoint > &) >
visit)
const std::shared_ptr< Endpoint > &) >
visit) const
{
auto itr = m_Endpoints.begin();
while(itr != m_Endpoints.end())
@ -66,7 +66,7 @@ namespace llarp
auto itr = m_Endpoints.find(name);
if(itr == m_Endpoints.end())
return false;
std::unique_ptr< Endpoint > ep = std::move(itr->second);
std::shared_ptr< Endpoint > ep = std::move(itr->second);
m_Endpoints.erase(itr);
ep->Stop();
m_Stopped.emplace_back(std::move(ep));
@ -96,20 +96,21 @@ namespace llarp
++itr;
}
}
auto ep = getFirstEndpoint();
if(!ep)
return;
std::vector< RouterID > expired;
m_Router->nodedb()->visit([&](const RouterContact &rc) -> bool {
if(rc.IsExpired(now))
expired.emplace_back(rc.pubkey);
return true;
});
// TODO: we need to stop looking up service nodes that are gone forever
// how do?
for(const auto &k : expired)
ep->LookupRouterAnon(k);
ForEachService([&](const std::string &,
const std::shared_ptr< Endpoint > &ep) -> bool {
// TODO: we need to stop looking up service nodes that are gone forever
// how do?
for(const auto &k : expired)
if(!ep->LookupRouterAnon(k))
return false;
return true;
});
}
bool
@ -118,68 +119,6 @@ namespace llarp
return m_Endpoints.size() ? true : false;
}
service::Endpoint *
Context::getFirstEndpoint()
{
if(!m_Endpoints.size())
{
LogError("No endpoints found");
return nullptr;
}
auto itr = m_Endpoints.begin();
if(itr == m_Endpoints.end())
return nullptr;
return itr->second.get();
}
bool
Context::iterate(struct endpoint_iter &i)
{
if(!m_Endpoints.size())
{
LogError("No endpoints found");
return false;
}
i.index = 0;
// util::Lock lock(access);
auto itr = m_Endpoints.begin();
while(itr != m_Endpoints.end())
{
i.endpoint = itr->second.get();
if(!i.visit(&i))
return false;
// advance
i.index++;
itr++;
}
return true;
}
handlers::TunEndpoint *
Context::getFirstTun()
{
service::Endpoint *endpointer = this->getFirstEndpoint();
if(!endpointer)
{
return nullptr;
}
handlers::TunEndpoint *tunEndpoint =
static_cast< handlers::TunEndpoint * >(endpointer);
return tunEndpoint;
}
llarp_tun_io *
Context::getRange()
{
handlers::TunEndpoint *tunEndpoint = this->getFirstTun();
if(!tunEndpoint)
{
LogError("No tunnel endpoint found");
return nullptr;
}
return &tunEndpoint->tunif;
}
bool
Context::FindBestAddressFor(const AlignedBuffer< 32 > &addr, bool isSNode,
huint32_t &ip)
@ -203,56 +142,6 @@ namespace llarp
return false;
}
bool
Context::Prefetch(const service::Address &addr)
{
handlers::TunEndpoint *tunEndpoint = this->getFirstTun();
if(!tunEndpoint)
{
LogError("No tunnel endpoint found");
return false;
}
// HiddenServiceAddresslookup *lookup = new
// HiddenServiceEndpoint(tunEndpoint, callback, addr,
// tunEndpoint->GenTXID());
return tunEndpoint->EnsurePathToService(
addr,
[](__attribute__((unused)) Address addr,
__attribute__((unused)) void *ctx) {},
10000);
}
bool
MapAddressAllIter(struct Context::endpoint_iter *endpointCfg)
{
Context::mapAddressAll_context *context =
(Context::mapAddressAll_context *)endpointCfg->user;
handlers::TunEndpoint *tunEndpoint =
(handlers::TunEndpoint *)endpointCfg->endpoint;
if(!tunEndpoint)
{
LogError("No tunnel endpoint found");
return true; // still continue
}
return tunEndpoint->MapAddress(
context->serviceAddr, context->localPrivateIpAddr.xtohl(), false);
}
bool
Context::MapAddressAll(const service::Address &addr,
Addr &localPrivateIpAddr)
{
struct Context::mapAddressAll_context context;
context.serviceAddr = addr;
context.localPrivateIpAddr = localPrivateIpAddr;
struct Context::endpoint_iter i;
i.user = &context;
i.index = 0;
i.visit = &MapAddressAllIter;
return this->iterate(i);
}
bool
Context::AddDefaultEndpoint(
const std::unordered_multimap< std::string, std::string > &opts)
@ -310,22 +199,38 @@ namespace llarp
keyfile = option.second;
}
std::unique_ptr< service::Endpoint > service;
service::Endpoint_ptr service;
static std::map<
std::string,
std::function< std::unique_ptr< service::Endpoint >(
std::function< service::Endpoint_ptr(
const std::string &, AbstractRouter *, service::Context *) > >
endpointConstructors = {
{"tun",
[](const std::string &nick, AbstractRouter *r,
service::Context *c) -> std::unique_ptr< service::Endpoint > {
return std::make_unique< handlers::TunEndpoint >(nick, r, c);
service::Context *c) -> service::Endpoint_ptr {
return std::make_shared< handlers::TunEndpoint >(nick, r, c);
}},
{"android-tun",
[](const std::string &, AbstractRouter *,
service::Context *) -> service::Endpoint_ptr {
return nullptr;
/// SOOOOOOON (tm)
// return std::make_shared<handlers::AndroidTunEndpoint>(nick,
// r, c);
}},
{"ios-tun",
[](const std::string &, AbstractRouter *,
service::Context *) -> service::Endpoint_ptr {
return nullptr;
/// SOOOOOOON (tm)
// return std::make_shared<handlers::IOSTunEndpoint>(nick, r,
// c);
}},
{"null",
[](const std::string &nick, AbstractRouter *r,
service::Context *c) -> std::unique_ptr< service::Endpoint > {
return std::make_unique< handlers::NullEndpoint >(nick, r, c);
service::Context *c) -> service::Endpoint_ptr {
return std::make_shared< handlers::NullEndpoint >(nick, r, c);
}}};
{
@ -339,18 +244,22 @@ namespace llarp
// construct
service = itr->second(conf.first, m_Router, this);
// if ephemeral, then we need to regen key
// if privkey file, then set it and load it
if(keyfile != "")
if(service)
{
service->SetOption("keyfile", keyfile);
// load keyfile, so we have the correct name for logging
// if ephemeral, then we need to regen key
// if privkey file, then set it and load it
if(keyfile != "")
{
service->SetOption("keyfile", keyfile);
// load keyfile, so we have the correct name for logging
}
LogInfo("Establishing endpoint identity");
service->LoadKeyFile(); // only start endpoint not tun
// now Name() will be correct
}
LogInfo("Establishing endpoint identity");
service->LoadKeyFile(); // only start endpoint not tun
// now Name() will be correct
}
if(service == nullptr)
return false;
// configure
for(const auto &option : conf.second)
{
@ -371,7 +280,7 @@ namespace llarp
if(service->Start())
{
LogInfo("autostarting hidden service endpoint ", service->Name());
m_Endpoints.emplace(conf.first, std::move(service));
m_Endpoints.emplace(conf.first, service);
return true;
}
LogError("failed to start hidden service endpoint ", conf.first);
@ -380,7 +289,7 @@ namespace llarp
else
{
LogInfo("added hidden service endpoint ", service->Name());
m_Endpoints.emplace(conf.first, std::move(service));
m_Endpoints.emplace(conf.first, service);
return true;
}
}

@ -31,51 +31,15 @@ namespace llarp
bool
hasEndpoints();
/// DRY refactor
service::Endpoint *
getFirstEndpoint();
bool
FindBestAddressFor(const AlignedBuffer< 32 > &addr, bool isSNode,
huint32_t &);
/// DRY refactor
handlers::TunEndpoint *
getFirstTun();
/// punch a hole to get ip range from first tun endpoint
llarp_tun_io *
getRange();
struct mapAddressAll_context
{
service::Address serviceAddr;
Addr localPrivateIpAddr;
};
struct endpoint_iter
{
void *user;
service::Endpoint *endpoint;
size_t index;
bool (*visit)(struct endpoint_iter *);
};
bool
iterate(struct endpoint_iter &i);
/// function visitor returns false to prematurely break iteration
void
ForEachService(std::function< bool(const std::string &,
const std::unique_ptr< Endpoint > &) >
visit);
/// hint at possible path usage and trigger building early
bool
Prefetch(const service::Address &addr);
bool
MapAddressAll(const service::Address &addr, Addr &localPrivateIpAddr);
ForEachService(
std::function< bool(const std::string &, const Endpoint_ptr &) >
visit) const;
/// add default endpoint with options
bool
@ -96,9 +60,9 @@ namespace llarp
private:
AbstractRouter *m_Router;
std::unordered_map< std::string, std::unique_ptr< Endpoint > >
std::unordered_map< std::string, std::shared_ptr< Endpoint > >
m_Endpoints;
std::list< std::unique_ptr< Endpoint > > m_Stopped;
std::list< std::shared_ptr< Endpoint > > m_Stopped;
};
} // namespace service
} // namespace llarp

@ -17,6 +17,7 @@
#include <util/logic.hpp>
#include <util/str.hpp>
#include <util/buffer.hpp>
#include <hook/shell.hpp>
namespace llarp
{
@ -64,6 +65,30 @@ namespace llarp
{
m_BundleRC = IsTrueValue(v.c_str());
}
if(k == "on-up")
{
m_OnUp = hooks::ExecShellBackend(v);
if(m_OnUp)
LogInfo(Name(), " added on up script: ", v);
else
LogError(Name(), " failed to add on up script");
}
if(k == "on-down")
{
m_OnDown = hooks::ExecShellBackend(v);
if(m_OnDown)
LogInfo(Name(), " added on down script: ", v);
else
LogError(Name(), " failed to add on down script");
}
if(k == "on-ready")
{
m_OnReady = hooks::ExecShellBackend(v);
if(m_OnReady)
LogInfo(Name(), " added on ready script: ", v);
else
LogError(Name(), " failed to add on ready script");
}
return true;
}
@ -145,11 +170,21 @@ namespace llarp
}
}
void
Endpoint::FlushSNodeTraffic()
bool
Endpoint::IsReady() const
{
std::for_each(m_SNodeSessions.begin(), m_SNodeSessions.end(),
[](auto& x) { x.second->Flush(); });
const auto now = Now();
if(m_IntroSet.I.size() == 0)
return false;
if(m_IntroSet.IsExpired(now))
return false;
return true;
}
bool
Endpoint::IntrosetIsStale() const
{
return m_IntroSet.HasExpiredIntros(Now());
}
util::StatusObject
@ -195,6 +230,7 @@ namespace llarp
void
Endpoint::Tick(llarp_time_t now)
{
path::Builder::Tick(now);
// publish descriptors
if(ShouldPublishDescriptors(now))
{
@ -285,6 +321,8 @@ namespace llarp
EndpointUtil::StopRemoteSessions(m_RemoteSessions);
// stop snode sessions
EndpointUtil::StopSnodeSessions(m_SNodeSessions);
if(m_OnDown)
m_OnDown->NotifyAsync(NotifyParams());
return path::Builder::Stop();
}
@ -507,6 +545,12 @@ namespace llarp
Endpoint::~Endpoint()
{
if(m_OnUp)
m_OnUp->Stop();
if(m_OnDown)
m_OnDown->Stop();
if(m_OnReady)
m_OnReady->Stop();
}
bool
@ -530,10 +574,10 @@ namespace llarp
{
}
std::unique_ptr< routing::IMessage >
std::shared_ptr< routing::IMessage >
BuildRequestMessage()
{
auto msg = std::make_unique< routing::DHTMessage >();
auto msg = std::make_shared< routing::DHTMessage >();
msg->M.emplace_back(
std::make_unique< dht::PublishIntroMessage >(m_IntroSet, txid, 1));
return msg;
@ -567,7 +611,7 @@ namespace llarp
}
bool
Endpoint::PublishIntroSetVia(AbstractRouter* r, path::Path* path)
Endpoint::PublishIntroSetVia(AbstractRouter* r, path::Path_ptr path)
{
auto job = new PublishIntroSetJob(this, GenTXID(), m_IntroSet);
if(job->SendRequestViaPath(path, r))
@ -586,7 +630,7 @@ namespace llarp
// make sure we have all paths that are established
// in our introset
bool should = false;
ForEachPath([&](const path::Path* p) {
ForEachPath([&](const path::Path_ptr& p) {
if(!p->IsReady())
return;
for(const auto& i : m_IntroSet.I)
@ -606,6 +650,9 @@ namespace llarp
{
m_LastPublish = Now();
LogInfo(Name(), " IntroSet publish confirmed");
if(m_OnReady)
m_OnReady->NotifyAsync(NotifyParams());
m_OnReady = nullptr;
}
bool
@ -654,7 +701,7 @@ namespace llarp
}
auto it = m_RemoteSessions.emplace(
addr, std::make_unique< OutboundContext >(introset, this));
addr, std::make_shared< OutboundContext >(introset, this));
LogInfo("Created New outbound context for ", addr.ToString());
// inform pending
@ -725,7 +772,7 @@ namespace llarp
}
void
Endpoint::HandlePathBuilt(path::Path* p)
Endpoint::HandlePathBuilt(path::Path_ptr p)
{
using namespace std::placeholders;
p->SetDataHandler(
@ -736,13 +783,20 @@ namespace llarp
}
bool
Endpoint::HandleDataDrop(path::Path* p, const PathID_t& dst, uint64_t seq)
Endpoint::HandleDataDrop(path::Path_ptr p, const PathID_t& dst,
uint64_t seq)
{
LogWarn(Name(), " message ", seq, " dropped by endpoint ", p->Endpoint(),
" via ", dst);
return true;
}
std::unordered_map< std::string, std::string >
Endpoint::NotifyParams() const
{
return {{"LOKINET_ADDR", m_Identity.pub.Addr().ToString()}};
}
bool
Endpoint::HandleDataMessage(const PathID_t& src, ProtocolMessage* msg)
{
@ -797,7 +851,7 @@ namespace llarp
}
bool
Endpoint::HandleHiddenServiceFrame(path::Path* p,
Endpoint::HandleHiddenServiceFrame(path::Path_ptr p,
const ProtocolFrame& frame)
{
if(frame.R)
@ -814,30 +868,33 @@ namespace llarp
RemoveConvoTag(frame.T);
return true;
}
if(!frame.AsyncDecryptAndVerify(EndpointLogic(), crypto(), p, Worker(),
m_Identity, m_DataHandler))
if(!frame.AsyncDecryptAndVerify(EndpointLogic(), crypto(), p,
CryptoWorker(), m_Identity,
m_DataHandler))
{
// send discard
ProtocolFrame f;
f.R = 1;
f.T = frame.T;
f.F = p->intro.pathID;
if(!f.Sign(crypto(), m_Identity))
return false;
const routing::PathTransferMessage d(f, frame.F);
return p->SendRoutingMessage(d, router);
auto d =
std::make_shared< const routing::PathTransferMessage >(f, frame.F);
RouterLogic()->queue_func([=]() { p->SendRoutingMessage(*d, router); });
return true;
}
return true;
}
void
Endpoint::HandlePathDied(path::Path*)
void Endpoint::HandlePathDied(path::Path_ptr)
{
RegenAndPublishIntroSet(Now(), true);
}
bool
Endpoint::CheckPathIsDead(path::Path*, llarp_time_t dlt)
Endpoint::CheckPathIsDead(path::Path_ptr, llarp_time_t dlt)
{
return dlt > path::alive_timeout;
}
@ -871,7 +928,7 @@ namespace llarp
ABSL_ATTRIBUTE_UNUSED llarp_time_t timeoutMS,
bool randomPath)
{
path::Path* path = nullptr;
path::Path_ptr path = nullptr;
if(randomPath)
path = PickRandomEstablishedPath();
else
@ -919,23 +976,26 @@ namespace llarp
using namespace std::placeholders;
if(m_SNodeSessions.count(snode) == 0)
{
auto themIP = ObtainIPForAddr(snode, true);
m_SNodeSessions.emplace(
auto themIP = ObtainIPForAddr(snode, true);
auto session = std::make_shared< exit::SNodeSession >(
snode,
std::make_unique< exit::SNodeSession >(
snode,
std::bind(&Endpoint::HandleWriteIPPacket, this, _1,
[themIP]() -> huint32_t { return themIP; }),
m_Router, 2, numHops));
std::bind(&Endpoint::HandleWriteIPPacket, this, _1,
[themIP]() -> huint32_t { return themIP; }),
m_Router, m_NumPaths, numHops);
m_SNodeSessions.emplace(snode, session);
}
EnsureRouterIsKnown(snode);
auto range = m_SNodeSessions.equal_range(snode);
auto itr = range.first;
while(itr != range.second)
{
if(itr->second->IsReady())
h(snode, itr->second.get());
h(snode, itr->second);
else
{
itr->second->AddReadyHook(std::bind(h, snode, _1));
itr->second->BuildOne();
}
++itr;
}
}
@ -944,23 +1004,32 @@ namespace llarp
Endpoint::SendToSNodeOrQueue(const RouterID& addr,
const llarp_buffer_t& buf)
{
net::IPv4Packet pkt;
if(!pkt.Load(buf))
auto pkt = std::make_shared< net::IPv4Packet >();
if(!pkt->Load(buf))
return false;
auto range = m_SNodeSessions.equal_range(addr);
auto itr = range.first;
while(itr != range.second)
{
if(itr->second->IsReady())
{
if(itr->second->QueueUpstreamTraffic(pkt, routing::ExitPadSize))
{
return true;
}
}
++itr;
}
return false;
EnsurePathToSNode(addr, [pkt](RouterID, exit::BaseSession_ptr s) {
if(s)
s->QueueUpstreamTraffic(*pkt, routing::ExitPadSize);
});
return true;
}
void Endpoint::Pump(llarp_time_t)
{
EndpointLogic()->queue_func([&]() {
for(const auto& item : m_SNodeSessions)
item.second->FlushDownstream();
});
auto router = Router();
for(const auto& item : m_RemoteSessions)
item.second->FlushUpstream();
for(const auto& item : m_SNodeSessions)
item.second->FlushUpstream();
util::Lock lock(&m_SendQueueMutex);
for(const auto& item : m_SendQueue)
item.second->SendRoutingMessage(*item.first, router);
m_SendQueue.clear();
}
bool
@ -976,9 +1045,9 @@ namespace llarp
auto itr = m_AddressToService.find(remote);
if(itr != m_AddressToService.end())
{
routing::PathTransferMessage transfer;
ProtocolFrame& f = transfer.T;
path::Path* p = nullptr;
auto transfer = std::make_shared< routing::PathTransferMessage >();
ProtocolFrame& f = transfer->T;
std::shared_ptr< path::Path > p;
std::set< ConvoTag > tags;
if(GetConvoTagsForService(itr->second, tags))
{
@ -1009,21 +1078,25 @@ namespace llarp
m.PutBuffer(data);
f.N.Randomize();
f.C.Zero();
transfer.Y.Randomize();
transfer->Y.Randomize();
m.proto = t;
m.introReply = p->intro;
PutReplyIntroFor(f.T, m.introReply);
m.sender = m_Identity.pub;
f.F = m.introReply.pathID;
f.S = GetSeqNoForConvo(f.T);
transfer.P = remoteIntro.pathID;
m.sender = m_Identity.pub;
f.F = m.introReply.pathID;
f.S = GetSeqNoForConvo(f.T);
transfer->P = remoteIntro.pathID;
if(!f.EncryptAndSign(Router()->crypto(), m, K, m_Identity))
{
LogError("failed to encrypt and sign");
return false;
}
LogDebug(Name(), " send ", data.sz, " via ", remoteIntro.router);
return p->SendRoutingMessage(transfer, Router());
{
util::Lock lock(&m_SendQueueMutex);
m_SendQueue.emplace_back(transfer, p);
}
return true;
}
}
}
@ -1043,12 +1116,18 @@ namespace llarp
++itr;
}
}
m_PendingTraffic[remote].emplace_back(data, t);
// no converstation
return EnsurePathToService(
remote,
[](Address, OutboundContext* c) {
[&](Address r, OutboundContext* c) {
if(c)
{
c->UpdateIntroSet(true);
for(auto& pending : m_PendingTraffic[r])
c->AsyncEncryptAndSendTo(pending.Buffer(), pending.protocol);
}
m_PendingTraffic.erase(r);
},
5000, true);
}
@ -1112,7 +1191,7 @@ namespace llarp
}
llarp_threadpool*
Endpoint::Worker()
Endpoint::CryptoWorker()
{
return m_Router->threadpool();
}

@ -14,6 +14,7 @@
#include <service/sendcontext.hpp>
#include <service/session.hpp>
#include <service/tag_lookup_job.hpp>
#include <hook/ihook.hpp>
// minimum time between introset shifts
#ifndef MIN_SHIFT_INTERVAL
@ -43,6 +44,18 @@ namespace llarp
Endpoint(const std::string& nickname, AbstractRouter* r, Context* parent);
~Endpoint();
/// return true if we are ready to recv packets from the void
bool
IsReady() const;
/// return true if our introset has expired intros
bool
IntrosetIsStale() const;
/// construct parameters for notify hooks
virtual std::unordered_map< std::string, std::string >
NotifyParams() const;
util::StatusObject
ExtractStatus() const;
@ -53,7 +66,7 @@ namespace llarp
SetOption(const std::string& k, const std::string& v);
virtual void
Tick(llarp_time_t now);
Tick(llarp_time_t now) override;
/// return true if we have a resolvable ip address
virtual bool
@ -70,22 +83,26 @@ namespace llarp
}
/// router's logic
/// use when sending any data on a path
Logic*
RouterLogic();
/// endpoint's logic
/// use when writing any data to local network interfaces
Logic*
EndpointLogic();
/// borrow endpoint's net loop for sending data to user
/// borrow endpoint's net loop for sending data to user on local network
/// interface
llarp_ev_loop_ptr
EndpointNetLoop();
Crypto*
crypto();
/// crypto worker threadpool
llarp_threadpool*
Worker();
CryptoWorker();
AbstractRouter*
Router()
@ -106,7 +123,7 @@ namespace llarp
ShouldPublishDescriptors(llarp_time_t now) const override;
void
HandlePathDied(path::Path* p) override;
HandlePathDied(path::Path_ptr p) override;
void
EnsureReplyPath(const ServiceInfo& addr);
@ -115,7 +132,7 @@ namespace llarp
PublishIntroSet(AbstractRouter* r) override;
bool
PublishIntroSetVia(AbstractRouter* r, path::Path* p);
PublishIntroSetVia(AbstractRouter* r, path::Path_ptr p);
bool
HandleGotIntroMessage(const dht::GotIntroMessage* msg) override;
@ -124,7 +141,7 @@ namespace llarp
HandleGotRouterMessage(const dht::GotRouterMessage* msg) override;
bool
HandleHiddenServiceFrame(path::Path* p,
HandleHiddenServiceFrame(path::Path_ptr p,
const service::ProtocolFrame& msg);
/// return true if we have an established path to a hidden service
@ -165,6 +182,10 @@ namespace llarp
bool
LookupRouterAnon(RouterID router);
/// called on event loop pump
virtual void
Pump(llarp_time_t now);
/// stop this endpoint
bool
Stop() override;
@ -179,7 +200,7 @@ namespace llarp
PutLookup(IServiceLookup* lookup, uint64_t txid) override;
void
HandlePathBuilt(path::Path* path) override;
HandlePathBuilt(path::Path_ptr path) override;
bool
SendToServiceOrQueue(const RouterID& addr, const llarp_buffer_t& payload,
@ -188,16 +209,13 @@ namespace llarp
bool
SendToSNodeOrQueue(const RouterID& addr, const llarp_buffer_t& payload);
void
FlushSNodeTraffic();
bool
HandleDataDrop(path::Path* p, const PathID_t& dst, uint64_t s);
HandleDataDrop(path::Path_ptr p, const PathID_t& dst, uint64_t s);
bool
CheckPathIsDead(path::Path* p, llarp_time_t latency);
CheckPathIsDead(path::Path_ptr p, llarp_time_t latency);
using PendingBufferQueue = std::queue< PendingBuffer >;
using PendingBufferQueue = std::deque< PendingBuffer >;
bool
ShouldBundleRC() const override;
@ -222,7 +240,7 @@ namespace llarp
uint64_t timeoutMS, bool lookupOnRandomPath = false);
using SNodeEnsureHook =
std::function< void(RouterID, exit::BaseSession*) >;
std::function< void(RouterID, exit::BaseSession_ptr) >;
/// ensure a path to a service node by public key
void
@ -329,7 +347,10 @@ namespace llarp
protected:
IDataHandler* m_DataHandler = nullptr;
Identity m_Identity;
std::unique_ptr< exit::BaseSession > m_Exit;
std::shared_ptr< exit::BaseSession > m_Exit;
hooks::Backend_ptr m_OnUp;
hooks::Backend_ptr m_OnDown;
hooks::Backend_ptr m_OnReady;
private:
friend struct EndpointUtil;
@ -343,21 +364,26 @@ namespace llarp
std::string m_NetNS;
bool m_BundleRC = false;
using Msg_ptr = std::shared_ptr< const routing::PathTransferMessage >;
using SendEvent_t = std::pair< Msg_ptr, path::Path_ptr >;
util::Mutex m_SendQueueMutex;
std::deque< SendEvent_t > m_SendQueue;
using PendingTraffic =
std::unordered_map< Address, PendingBufferQueue, Address::Hash >;
PendingTraffic m_PendingTraffic;
using Sessions =
std::unordered_multimap< Address, std::unique_ptr< OutboundContext >,
std::unordered_multimap< Address, std::shared_ptr< OutboundContext >,
Address::Hash >;
Sessions m_RemoteSessions;
Sessions m_DeadSessions;
using SNodeSessions = std::unordered_multimap<
RouterID, std::unique_ptr< exit::BaseSession >, RouterID::Hash >;
RouterID, std::shared_ptr< exit::BaseSession >, RouterID::Hash >;
util::Mutex m_SNodeSessionsMutex;
SNodeSessions m_SNodeSessions;
std::unordered_map< Address, ServiceInfo, Address::Hash >
@ -420,6 +446,9 @@ namespace llarp
std::unordered_map< Tag, CachedTagResult, Tag::Hash > m_PrefetchedTags;
};
using Endpoint_ptr = std::shared_ptr< Endpoint >;
} // namespace service
} // namespace llarp

@ -24,6 +24,10 @@ namespace llarp
{
itr->second->Stop();
}
else
{
itr->second->Tick(now);
}
++itr;
}
@ -90,7 +94,8 @@ namespace llarp
auto itr = remoteSessions.begin();
while(itr != remoteSessions.end())
{
if(itr->second->Tick(now))
itr->second->Tick(now);
if(itr->second->Pump(now))
{
itr->second->Stop();
deadSessions.emplace(std::move(*itr));

@ -33,12 +33,12 @@ namespace llarp
return handle(remote, nullptr, endpoint);
}
std::unique_ptr< routing::IMessage >
std::shared_ptr< routing::IMessage >
HiddenServiceAddressLookup::BuildRequestMessage()
{
auto msg = std::make_unique< routing::DHTMessage >();
auto msg = std::make_shared< routing::DHTMessage >();
msg->M.emplace_back(
std::make_unique< dht::FindIntroMessage >(txid, remote, 0));
std::make_unique< dht::FindIntroMessage >(txid, remote, true));
return msg;
}

@ -27,7 +27,7 @@ namespace llarp
bool
HandleResponse(const std::set< IntroSet >& results);
std::unique_ptr< routing::IMessage >
std::shared_ptr< routing::IMessage >
BuildRequestMessage();
};
} // namespace service

@ -70,7 +70,7 @@ namespace llarp
Introduction::print(std::ostream& stream, int level, int spaces) const
{
Printer printer(stream, level, spaces);
printer.printAttribute("k", router);
printer.printAttribute("k", RouterID(router));
printer.printAttribute("p", pathID);
printer.printAttribute("v", version);
printer.printAttribute("x", expiresAt);

@ -2,6 +2,8 @@
#include <path/path.hpp>
#include <util/time.hpp>
#include <router/abstractrouter.hpp>
#include <util/logic.hpp>
namespace llarp
{
@ -18,14 +20,14 @@ namespace llarp
}
bool
IServiceLookup::SendRequestViaPath(path::Path *path, AbstractRouter *r)
IServiceLookup::SendRequestViaPath(path::Path_ptr path, AbstractRouter *r)
{
auto msg = BuildRequestMessage();
if(!msg)
return false;
auto result = path->SendRoutingMessage(*msg, r);
endpoint = path->Endpoint();
return result;
endpoint = path->Endpoint();
r->logic()->queue_func([=]() { path->SendRoutingMessage(*msg, r); });
return true;
}
} // namespace service
} // namespace llarp

@ -3,6 +3,7 @@
#include <routing/message.hpp>
#include <service/intro_set.hpp>
#include <path/pathset.hpp>
#include <set>
@ -45,12 +46,12 @@ namespace llarp
}
/// build request message for service lookup
virtual std::unique_ptr< routing::IMessage >
virtual std::shared_ptr< routing::IMessage >
BuildRequestMessage() = 0;
/// build a new request message and send it via a path
bool
SendRequestViaPath(path::Path* p, AbstractRouter* r);
SendRequestViaPath(path::Path_ptr p, AbstractRouter* r);
ILookupHolder* parent;
uint64_t txid;

@ -32,7 +32,7 @@ namespace llarp
}
bool
OutboundContext::HandleDataDrop(path::Path* p, const PathID_t& dst,
OutboundContext::HandleDataDrop(path::Path_ptr p, const PathID_t& dst,
uint64_t seq)
{
// pick another intro
@ -122,7 +122,7 @@ namespace llarp
}
void
OutboundContext::HandlePathBuilt(path::Path* p)
OutboundContext::HandlePathBuilt(path::Path_ptr p)
{
path::Builder::HandlePathBuilt(p);
/// don't use it if we are marked bad
@ -178,9 +178,9 @@ namespace llarp
void
OutboundContext::AsyncGenIntro(const llarp_buffer_t& payload,
__attribute__((unused)) ProtocolType t)
ProtocolType t)
{
auto path = m_PathSet->GetPathByRouter(remoteIntro.router);
auto path = m_PathSet->GetNewestPathByRouter(remoteIntro.router);
if(path == nullptr)
{
// try parent as fallback
@ -199,12 +199,14 @@ namespace llarp
m_Endpoint->GetIdentity(), currentIntroSet.K, remoteIntro,
m_DataHandler, currentConvoTag);
ex->hook = std::bind(&OutboundContext::Send, this, std::placeholders::_1);
ex->hook =
std::bind(&OutboundContext::Send, this, std::placeholders::_1, path);
ex->msg.PutBuffer(payload);
ex->msg.proto = t;
ex->msg.introReply = path->intro;
ex->frame.F = ex->msg.introReply.pathID;
llarp_threadpool_queue_job(m_Endpoint->Worker(),
llarp_threadpool_queue_job(m_Endpoint->CryptoWorker(),
{ex, &AsyncKeyExchange::Encrypt});
}
@ -222,7 +224,7 @@ namespace llarp
return;
auto addr = currentIntroSet.A.Addr();
path::Path* path = nullptr;
path::Path_ptr path = nullptr;
if(randomizePath)
path = m_Endpoint->PickRandomEstablishedPath();
else
@ -274,7 +276,7 @@ namespace llarp
}
bool
OutboundContext::Tick(llarp_time_t now)
OutboundContext::Pump(llarp_time_t now)
{
// we are probably dead af
if(m_LookupFails > 16 || m_BuildFails > 10)
@ -470,7 +472,7 @@ namespace llarp
}
void
OutboundContext::HandlePathDied(path::Path* path)
OutboundContext::HandlePathDied(path::Path_ptr path)
{
// unconditionally update introset
UpdateIntroSet(true);
@ -480,7 +482,7 @@ namespace llarp
{
// figure out how many paths to this router we have
size_t num = 0;
ForEachPath([&](path::Path* p) {
ForEachPath([&](const path::Path_ptr& p) {
if(p->Endpoint() == endpoint && p->IsReady())
++num;
});
@ -491,7 +493,7 @@ namespace llarp
if(num == 1)
{
num = 0;
ForEachPath([&](path::Path* p) {
ForEachPath([&](const path::Path_ptr& p) {
if(p->Endpoint() == endpoint)
++num;
});
@ -521,7 +523,7 @@ namespace llarp
m_NextIntro = picked;
// check if we have a path to this router
num = 0;
ForEachPath([&](path::Path* p) {
ForEachPath([&](const path::Path_ptr& p) {
if(p->Endpoint() == m_NextIntro.router)
++num;
});
@ -534,7 +536,7 @@ namespace llarp
}
bool
OutboundContext::HandleHiddenServiceFrame(path::Path* p,
OutboundContext::HandleHiddenServiceFrame(path::Path_ptr p,
const ProtocolFrame& frame)
{
return m_Endpoint->HandleHiddenServiceFrame(p, frame);

@ -15,7 +15,10 @@ namespace llarp
struct Endpoint;
/// context needed to initiate an outbound hidden service session
struct OutboundContext : public path::Builder, public SendContext
struct OutboundContext
: public path::Builder,
public SendContext,
public std::enable_shared_from_this< OutboundContext >
{
OutboundContext(const IntroSet& introSet, Endpoint* parent);
~OutboundContext();
@ -26,14 +29,20 @@ namespace llarp
bool
ShouldBundleRC() const override;
path::PathSet_ptr
GetSelf() override
{
return shared_from_this();
}
bool
Stop() override;
bool
HandleDataDrop(path::Path* p, const PathID_t& dst, uint64_t s);
HandleDataDrop(path::Path_ptr p, const PathID_t& dst, uint64_t s);
void
HandlePathDied(path::Path* p) override;
HandlePathDied(path::Path_ptr p) override;
/// set to true if we are updating the remote introset right now
bool updatingIntroSet;
@ -54,17 +63,17 @@ namespace llarp
bool
ShouldBuildMore(llarp_time_t now) const override;
/// tick internal state
/// pump internal state
/// return true to mark as dead
bool
Tick(llarp_time_t now);
Pump(llarp_time_t now);
/// return true if it's safe to remove ourselves
bool
IsDone(llarp_time_t now) const;
bool
CheckPathIsDead(path::Path* p, llarp_time_t dlt);
CheckPathIsDead(path::Path_ptr p, llarp_time_t dlt);
void
AsyncGenIntro(const llarp_buffer_t& payload, ProtocolType t) override;
@ -77,14 +86,14 @@ namespace llarp
BuildOneAlignedTo(const RouterID& remote);
void
HandlePathBuilt(path::Path* path) override;
HandlePathBuilt(path::Path_ptr path) override;
bool
SelectHop(llarp_nodedb* db, const RouterContact& prev, RouterContact& cur,
size_t hop, path::PathRole roles) override;
bool
HandleHiddenServiceFrame(path::Path* p, const ProtocolFrame& frame);
HandleHiddenServiceFrame(path::Path_ptr p, const ProtocolFrame& frame);
std::string
Name() const override;

@ -363,7 +363,7 @@ namespace llarp
bool
ProtocolFrame::AsyncDecryptAndVerify(Logic* logic, Crypto* c,
path::Path* recvPath,
path::Path_ptr recvPath,
llarp_threadpool* worker,
const Identity& localIdent,
IDataHandler* handler) const

@ -11,6 +11,7 @@
#include <service/handler.hpp>
#include <util/bencode.hpp>
#include <util/time.hpp>
#include <path/pathset.hpp>
#include <vector>
@ -118,7 +119,7 @@ namespace llarp
Sign(Crypto* c, const Identity& localIdent);
bool
AsyncDecryptAndVerify(Logic* logic, Crypto* c, path::Path* fromPath,
AsyncDecryptAndVerify(Logic* logic, Crypto* c, path::Path_ptr fromPath,
llarp_threadpool* worker,
const Identity& localIdent,
IDataHandler* handler) const;

@ -3,6 +3,7 @@
#include <messages/path_transfer.hpp>
#include <service/endpoint.hpp>
#include <router/abstractrouter.hpp>
#include <util/logic.hpp>
namespace llarp
{
@ -22,26 +23,33 @@ namespace llarp
}
bool
SendContext::Send(const ProtocolFrame& msg)
SendContext::Send(const ProtocolFrame& msg, path::Path_ptr path)
{
auto path = m_PathSet->GetByEndpointWithID(remoteIntro.router, msg.F);
if(path)
auto transfer = std::make_shared< const routing::PathTransferMessage >(
msg, remoteIntro.pathID);
{
const routing::PathTransferMessage transfer(msg, remoteIntro.pathID);
if(path->SendRoutingMessage(transfer, m_Endpoint->Router()))
util::Lock lock(&m_SendQueueMutex);
m_SendQueue.emplace_back(transfer, path);
}
return true;
}
void
SendContext::FlushUpstream()
{
auto r = m_Endpoint->Router();
util::Lock lock(&m_SendQueueMutex);
for(const auto& item : m_SendQueue)
{
if(item.second->SendRoutingMessage(*item.first, r))
{
LogInfo("sent intro to ", remoteIntro.pathID, " on ",
remoteIntro.router, " seqno=", sequenceNo);
lastGoodSend = m_Endpoint->Now();
lastGoodSend = r->Now();
++sequenceNo;
return true;
}
else
LogError("Failed to send frame on path");
}
else
LogError("cannot send because we have no path to ", remoteIntro.router);
return false;
m_SendQueue.clear();
}
/// send on an established convo tag
@ -50,8 +58,7 @@ namespace llarp
{
auto crypto = m_Endpoint->Router()->crypto();
SharedSecret shared;
routing::PathTransferMessage msg;
ProtocolFrame& f = msg.T;
ProtocolFrame f;
f.N.Randomize();
f.T = currentConvoTag;
f.S = m_Endpoint->GetSeqNoForConvo(f.T);
@ -94,20 +101,8 @@ namespace llarp
LogError("No cached session key");
return;
}
msg.P = remoteIntro.pathID;
msg.Y.Randomize();
if(path->SendRoutingMessage(msg, m_Endpoint->Router()))
{
LogDebug("sent message via ", remoteIntro.pathID, " on ",
remoteIntro.router);
++sequenceNo;
lastGoodSend = now;
}
else
{
LogWarn("Failed to send routing message for data");
}
++sequenceNo;
Send(f, path);
}
void

@ -1,11 +1,12 @@
#ifndef LLARP_SERVICE_SENDCONTEXT_HPP
#define LLARP_SERVICE_SENDCONTEXT_HPP
#include <messages/path_transfer.hpp>
#include <path/pathset.hpp>
#include <service/intro.hpp>
#include <service/protocol.hpp>
#include <util/buffer.hpp>
#include <util/types.hpp>
#include <deque>
namespace llarp
{
@ -23,24 +24,33 @@ namespace llarp
void
AsyncEncryptAndSendTo(const llarp_buffer_t& payload, ProtocolType t);
/// send a fully encrypted hidden service frame
/// via a path on our pathset with path id p
/// queue send a fully encrypted hidden service frame
/// via a path
bool
Send(const ProtocolFrame& f);
Send(const ProtocolFrame& f, path::Path_ptr path)
LOCKS_EXCLUDED(m_SendQueueMutex);
/// flush upstream traffic when in router thread
void
FlushUpstream() LOCKS_EXCLUDED(m_SendQueueMutex);
SharedSecret sharedKey;
ServiceInfo remoteIdent;
Introduction remoteIntro;
ConvoTag currentConvoTag;
path::PathSet* m_PathSet;
IDataHandler* m_DataHandler;
Endpoint* m_Endpoint;
path::PathSet* const m_PathSet;
IDataHandler* const m_DataHandler;
Endpoint* const m_Endpoint;
uint64_t sequenceNo = 0;
llarp_time_t lastGoodSend = 0;
llarp_time_t createdAt;
llarp_time_t sendTimeout = 40 * 1000;
llarp_time_t connectTimeout = 60 * 1000;
bool markedBad = false;
using Msg_ptr = std::shared_ptr< const routing::PathTransferMessage >;
using SendEvent_t = std::pair< Msg_ptr, path::Path_ptr >;
util::Mutex m_SendQueueMutex;
std::deque< SendEvent_t > m_SendQueue;
virtual bool
ShiftIntroduction(bool rebuild = true)

@ -42,10 +42,10 @@ namespace llarp
}
}
std::unique_ptr< routing::IMessage >
std::shared_ptr< routing::IMessage >
CachedTagResult::BuildRequestMessage(uint64_t txid)
{
auto msg = std::make_unique< routing::DHTMessage >();
auto msg = std::make_shared< routing::DHTMessage >();
msg->M.emplace_back(std::make_unique< dht::FindIntroMessage >(tag, txid));
lastRequest = parent->Now();
return msg;

@ -43,7 +43,7 @@ namespace llarp
return (now - lastRequest) > TTL;
}
std::unique_ptr< routing::IMessage >
std::shared_ptr< routing::IMessage >
BuildRequestMessage(uint64_t txid);
bool
@ -58,7 +58,7 @@ namespace llarp
{
}
std::unique_ptr< routing::IMessage >
std::shared_ptr< routing::IMessage >
BuildRequestMessage() override
{
return m_result->BuildRequestMessage(txid);

@ -128,7 +128,7 @@ struct llarp_buffer_t
#ifndef _WIN32
bool
writef(const char *fmt, ...) __attribute__((format(printf, 2, 3)));
#elif defined(__MINGW64__) || defined(__MINGW32__)
bool
writef(const char *fmt, ...)

@ -14,7 +14,9 @@ namespace llarp
{
struct IParser
{
virtual ~IParser(){}
virtual ~IParser()
{
}
/// result from feeding data to parser
enum Result

@ -57,7 +57,8 @@ namespace llarp
(void)ts;
return out << time_now_ms();
#else
return out << absl::FormatTime(ts.format, absl::Now(), absl::LocalTimeZone());
return out << absl::FormatTime(ts.format, absl::Now(),
absl::LocalTimeZone());
#endif
}
};

@ -16,8 +16,8 @@ struct llarp_threadpool
std::queue< std::function< void(void) > > jobs GUARDED_BY(m_access);
llarp_threadpool(int workers, const char *name)
: impl(std::make_unique< llarp::thread::ThreadPool >(workers,
workers * 128))
: impl(
std::make_unique< llarp::thread::ThreadPool >(workers, workers * 128))
{
(void)name;
}

@ -184,7 +184,7 @@ upoll_wait_select(upoll_t* upq, upoll_event_t* evs, int nev, int timeout)
if(nev > FD_SETSIZE)
nev = FD_SETSIZE;
unote_t** nvec = calloc(nev, sizeof(unote_t *));
unote_t** nvec = calloc(nev, sizeof(unote_t*));
int i, maxfd = 0, e = 0, nfds = 0;
fd_set pollin, pollout, pollerr;

@ -11,6 +11,7 @@
struct DNSLibTest : public ::testing::Test
{
const std::string tld = ".loki";
std::array< byte_t, 1500 > mem;
llarp_buffer_t buf;
@ -27,6 +28,23 @@ struct DNSLibTest : public ::testing::Test
}
};
TEST_F(DNSLibTest, TestHasTLD)
{
llarp::dns::Question question;
question.qname = "a.loki.";
ASSERT_TRUE(question.HasTLD(tld));
question.qname = "a.loki..";
ASSERT_FALSE(question.HasTLD(tld));
question.qname = "bepis.loki.";
ASSERT_TRUE(question.HasTLD(tld));
question.qname = "bepis.logi.";
ASSERT_FALSE(question.HasTLD(tld));
question.qname = "a.net.";
ASSERT_FALSE(question.HasTLD(tld));
question.qname = "a.boki.";
ASSERT_FALSE(question.HasTLD(tld));
};
TEST_F(DNSLibTest, TestPTR)
{
llarp::huint32_t ip = {0};

Loading…
Cancel
Save