add shell based hooks for service::Endpoint, also make format

pull/576/head
Jeff Becker 5 years ago
parent 73a71e43c3
commit 3a8cb0bfb5
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -117,7 +117,7 @@ main(int argc, char *argv[])
("config","path to configuration file", cxxopts::value<std::string>());
options.parse_positional("config");
// clang-format on
// clang-format on
bool genconfigOnly = false;
bool asRouter = false;
@ -154,7 +154,7 @@ main(int argc, char *argv[])
asRouter = true;
}
if(result.count("config") > 0)
if(result.count("config") > 0)
{
auto arg = result["config"].as< std::string >();
if(!arg.empty())
@ -163,7 +163,7 @@ main(int argc, char *argv[])
}
}
}
catch (const cxxopts::option_not_exists_exception& ex)
catch(const cxxopts::option_not_exists_exception &ex)
{
std::cerr << ex.what();
return printHelp(argv[0]);

@ -50,8 +50,7 @@ struct DemoCall : public abyss::http::IRPCClientHandler
}
void
PopulateReqHeaders(ABSL_ATTRIBUTE_UNUSED
abyss::http::Headers_t& hdr) override
PopulateReqHeaders(ABSL_ATTRIBUTE_UNUSED abyss::http::Headers_t& hdr) override
{
}

@ -173,6 +173,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

@ -643,8 +643,7 @@ extern "C"
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 +651,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 +673,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();
}
}

@ -23,8 +23,8 @@ dns_iptracker_init()
// 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)
dns_iptracker_setup_dotLokiLookup(
dotLokiLookup *dll, ABSL_ATTRIBUTE_UNUSED llarp::huint32_t tunGatewayIp)
{
dll->ip_tracker = &g_dns_iptracker;
return true;

@ -539,6 +539,14 @@ 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)
{
std::unordered_map< std::string, std::string > env = NotifyParams();
env.emplace("IP_ADDR", m_OurIP.ToString());
env.emplace("IF_ADDR", m_OurRange.ToString());
env.emplace("IF_NAME", tunif.ifname);
m_OnUp->NotifyAsync(std::move(env));
}
return true;
}

@ -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,81 @@
#include <hook/shell.hpp>
#include <util/thread_pool.hpp>
#include <util/logger.hpp>
namespace llarp
{
namespace hooks
{
struct ExecShellHookJob
: public std::enable_shared_from_this< 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(std::move(f)), m_env(std::move(_env))
{
}
void
Work()
{
char *const _args[] = {0};
std::vector< std::string > _env(m_env.size() + 1);
std::vector< char * > env;
for(const auto &item : m_env)
{
_env.emplace_back(item.first + "=" + item.second);
env.emplace_back(_env.back().c_str());
}
env.emplace_back(nullptr);
auto code = ::execvpe(m_File.c_str(), _args, env.data());
LogInfo(m_File, " : ", code);
}
};
struct ExecShellHookBackend : public IBackend
{
ExecShellHookBackend(std::string script)
: m_ThreadPool(1, 8), m_ScriptFile(std::move(script))
{
}
llarp::thread::ThreadPool m_ThreadPool;
const std::string m_ScriptFile;
bool
Start() override
{
return m_ThreadPool.start();
}
bool
Stop() override
{
m_ThreadPool.stop();
return true;
}
void
NotifyAsync(
std::unordered_map< std::string, std::string > params) override
{
auto job = std::make_shared< ExecShellHookJob >(m_ScriptFile,
std::move(params));
m_ThreadPool.addJob(
std::bind(&ExecShellHookJob::Work, job->shared_from_this()));
}
};
Backend_ptr
ExecShellBackend(std::string execFilePath)
{
Backend_ptr ptr = std::make_unique< ExecShellHookBackend >(execFilePath);
if(!ptr->Start())
return nullptr;
return ptr;
}
} // 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

@ -329,7 +329,7 @@ namespace llarp
using namespace std::placeholders;
if(self->record.work
&& self->record.work->IsValid(
std::bind(&Crypto::shorthash, crypto, _1, _2), now))
std::bind(&Crypto::shorthash, crypto, _1, _2), now))
{
llarp::LogDebug("LRCM extended lifetime by ",
self->record.work->extendedLifetime, " seconds for ",

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

@ -172,24 +172,26 @@ namespace llarp
IHopHandler*
PathContext::GetByUpstream(const RouterID& remote, const PathID_t& id)
{
auto own = MapGet(m_OurPaths, id,
[](__attribute__((unused)) const PathSet* s) -> bool {
// TODO: is this right?
return true;
},
[remote, id](PathSet* p) -> IHopHandler* {
return p->GetByUpstream(remote, id);
});
auto own = MapGet(
m_OurPaths, id,
[](__attribute__((unused)) const PathSet* s) -> bool {
// TODO: is this right?
return true;
},
[remote, id](PathSet* p) -> IHopHandler* {
return p->GetByUpstream(remote, id);
});
if(own)
return own;
return MapGet(m_TransitPaths, id,
[remote](const std::shared_ptr< TransitHop >& hop) -> bool {
return hop->info.upstream == remote;
},
[](const std::shared_ptr< TransitHop >& h) -> IHopHandler* {
return h.get();
});
return MapGet(
m_TransitPaths, id,
[remote](const std::shared_ptr< TransitHop >& hop) -> bool {
return hop->info.upstream == remote;
},
[](const std::shared_ptr< TransitHop >& h) -> IHopHandler* {
return h.get();
});
}
bool
@ -206,13 +208,14 @@ namespace llarp
IHopHandler*
PathContext::GetByDownstream(const RouterID& remote, const PathID_t& id)
{
return MapGet(m_TransitPaths, id,
[remote](const std::shared_ptr< TransitHop >& hop) -> bool {
return hop->info.downstream == remote;
},
[](const std::shared_ptr< TransitHop >& h) -> IHopHandler* {
return h.get();
});
return MapGet(
m_TransitPaths, id,
[remote](const std::shared_ptr< TransitHop >& hop) -> bool {
return hop->info.downstream == remote;
},
[](const std::shared_ptr< TransitHop >& h) -> IHopHandler* {
return h.get();
});
}
PathSet*

@ -143,9 +143,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;

@ -1569,9 +1569,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)
{

@ -206,6 +206,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;

@ -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::unique_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;
}
};

@ -48,7 +48,7 @@ namespace llarp
Context::ForEachService(
std::function< bool(const std::string &,
const std::unique_ptr< Endpoint > &) >
visit)
visit) const
{
auto itr = m_Endpoints.begin();
while(itr != m_Endpoints.end())

@ -68,7 +68,7 @@ namespace llarp
void
ForEachService(std::function< bool(const std::string &,
const std::unique_ptr< Endpoint > &) >
visit);
visit) const;
/// hint at possible path usage and trigger building early
bool

@ -16,6 +16,7 @@
#include <util/logic.hpp>
#include <util/str.hpp>
#include <util/buffer.hpp>
#include <hook/shell.hpp>
namespace llarp
{
@ -63,6 +64,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;
}
@ -155,6 +180,23 @@ namespace llarp
}
}
bool
Endpoint::IsReady() const
{
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
Endpoint::ExtractStatus() const
{
@ -367,6 +409,8 @@ namespace llarp
{
item.second->Stop();
}
if(m_OnDown)
m_OnDown->NotifyAsync(NotifyParams());
return path::Builder::Stop();
}
@ -597,6 +641,12 @@ namespace llarp
Endpoint::~Endpoint()
{
if(m_OnUp)
m_OnUp->Stop();
if(m_OnDown)
m_OnDown->Stop();
if(m_OnReady)
m_OnReady->Stop();
}
bool
@ -695,6 +745,9 @@ namespace llarp
{
m_LastPublish = Now();
LogInfo(Name(), " IntroSet publish confirmed");
if(m_OnReady)
m_OnReady->NotifyAsync(NotifyParams());
m_OnReady = nullptr;
}
bool
@ -835,6 +888,12 @@ namespace llarp
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)
{
@ -899,22 +958,22 @@ namespace llarp
if(!GetSenderFor(frame->T, si))
return false;
// verify source
if(!frame->Verify(Crypto(), si))
if(!frame->Verify(GetCrypto(), si))
return false;
// remove convotag it doesn't exist
LogWarn("remove convotag T=", frame->T);
RemoveConvoTag(frame->T);
return true;
}
if(!frame->AsyncDecryptAndVerify(EndpointLogic(), Crypto(), p, Worker(),
m_Identity, m_DataHandler))
if(!frame->AsyncDecryptAndVerify(EndpointLogic(), GetCrypto(), p,
Worker(), 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))
if(!f.Sign(GetCrypto(), m_Identity))
return false;
const routing::PathTransferMessage d(f, frame->F);
return p->SendRoutingMessage(&d, router);
@ -1200,7 +1259,7 @@ namespace llarp
}
Crypto*
Endpoint::Crypto()
Endpoint::GetCrypto()
{
return m_Router->crypto();
}

@ -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
std::unordered_map< std::string, std::string >
NotifyParams() const;
util::StatusObject
ExtractStatus() const;
@ -82,7 +95,7 @@ namespace llarp
EndpointNetLoop();
Crypto*
Crypto();
GetCrypto();
llarp_threadpool*
Worker();
@ -330,6 +343,9 @@ namespace llarp
IDataHandler* m_DataHandler = nullptr;
Identity m_Identity;
std::unique_ptr< exit::BaseSession > m_Exit;
hooks::Backend_ptr m_OnUp;
hooks::Backend_ptr m_OnDown;
hooks::Backend_ptr m_OnReady;
private:
AbstractRouter* m_Router;

@ -195,7 +195,7 @@ namespace llarp
}
currentConvoTag.Randomize();
AsyncKeyExchange* ex = new AsyncKeyExchange(
m_Endpoint->RouterLogic(), m_Endpoint->Crypto(), remoteIdent,
m_Endpoint->RouterLogic(), m_Endpoint->GetCrypto(), remoteIdent,
m_Endpoint->GetIdentity(), currentIntroSet.K, remoteIntro,
m_DataHandler, currentConvoTag);

@ -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, ...)

@ -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;

Loading…
Cancel
Save