add introspection rpc endpoint

pull/300/head
Jeff Becker 5 years ago
parent 6fa10019d0
commit e1522faeaa
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -332,6 +332,7 @@ set(LIB_UTIL_SRC
llarp/util/mem.cpp
llarp/util/queue_manager.cpp
llarp/util/queue.cpp
llarp/util/status.cpp
llarp/util/str.cpp
llarp/util/string_view.cpp
llarp/util/thread_pool.cpp

@ -2,18 +2,6 @@
#define __ABYSS_JSON_JSON_HPP
#include <memory>
//#if __cplusplus >= 201703L
#if 0
#include <unordered_map>
#include <any>
namespace abyss
{
namespace json
{
using Object = std::unordered_map< std::string, std::any >;
}
} // namespace abyss
#else
#include <rapidjson/document.h>
namespace abyss
{
@ -22,10 +10,7 @@ namespace abyss
using Document = rapidjson::Document;
using Value = rapidjson::Value;
} // namespace json
} // namespace abyss
#endif
namespace abyss
{
#if __cplusplus >= 201703L
using string_view = std::string_view;
#else

@ -3,6 +3,7 @@
#include <dht/kademlia.hpp>
#include <dht/key.hpp>
#include <util/status.hpp>
#include <map>
#include <set>
@ -13,13 +14,25 @@ namespace llarp
namespace dht
{
template < typename Val_t >
struct Bucket
struct Bucket : public util::IStateful
{
using BucketStorage_t = std::map< Key_t, Val_t, XorMetric >;
using Random_t = std::function< uint64_t() >;
Bucket(const Key_t& us, Random_t r) : nodes(XorMetric(us)), random(r){};
void
ExtractStatus(util::StatusObject& obj) const override
{
for(const auto& item : nodes)
{
std::string keyname = item.first.ToHex();
util::StatusObject itemObj;
item.second.ExtractStatus(itemObj);
obj.PutObject(keyname.c_str(), itemObj);
}
}
size_t
size() const
{

@ -222,6 +222,28 @@ namespace llarp
pendingExploreLookups.Expire(now);
}
void
Context::ExtractStatus(util::StatusObject &obj) const
{
util::StatusObject pendingRouterObj, pendingIntrosetObj, pendingTagObj,
pendingExploreObj, routerBucketObj, serviceBucketObj;
pendingRouterLookups.ExtractStatus(pendingRouterObj);
pendingIntrosetLookups.ExtractStatus(pendingIntrosetObj);
pendingTagLookups.ExtractStatus(pendingTagObj);
pendingExploreLookups.ExtractStatus(pendingExploreObj);
nodes->ExtractStatus(routerBucketObj);
services->ExtractStatus(serviceBucketObj);
obj.PutObject("pendingRouterLookups", pendingRouterObj);
obj.PutObject("pendingIntrosetLookups", pendingIntrosetObj);
obj.PutObject("pendingTagLookups", pendingTagObj);
obj.PutObject("pendingExploreLookups", pendingExploreObj);
obj.PutObject("nodes", routerBucketObj);
obj.PutObject("services", serviceBucketObj);
obj.PutString("ourKey", ourKey.ToHex());
}
void
Context::Init(const Key_t &us, llarp::Router *r,
llarp_time_t exploreInterval)

@ -12,6 +12,7 @@
#include <dht/txowner.hpp>
#include <service/IntroSet.hpp>
#include <util/time.hpp>
#include <util/status.hpp>
#include <set>
@ -68,7 +69,7 @@ namespace llarp
Nodes() const = 0;
};
struct Context final : public AbstractContext
struct Context final : public AbstractContext, public util::IStateful
{
Context();
@ -76,6 +77,9 @@ namespace llarp
{
}
void
ExtractStatus(util::StatusObject& obj) const override;
llarp::Crypto*
Crypto() const override;

@ -31,6 +31,29 @@ namespace llarp
return false;
}
void
ExtractStatus(util::StatusObject &obj) const override
{
std::vector< std::string > foundObjs;
for(const auto &found : valuesFound)
{
foundObjs.emplace_back(found.ToHex());
}
obj.PutStringArray("found", foundObjs);
util::StatusObject txownerObj;
txownerObj.PutInt("txid", whoasked.txid);
txownerObj.PutString("node", whoasked.node.ToHex());
obj.PutObject("whoasked", txownerObj);
std::vector< std::string > asked;
for(const auto &peer : peersAsked)
asked.emplace_back(peer.ToHex());
obj.PutStringArray("asked", asked);
obj.PutString("target", target.ToHex());
}
void
DoNextRequest(const Key_t &) override
{

@ -32,6 +32,17 @@ namespace llarp
localPath);
return;
}
if(valuesFound.size())
{
RouterContact found;
for(const auto &rc : valuesFound)
{
if(rc.OtherIsNewer(found))
found = rc;
}
valuesFound.clear();
valuesFound.emplace_back(found);
}
routing::DHTMessage msg;
msg.M.emplace_back(new GotRouterMessage(parent->OurKey(), whoasked.txid,
valuesFound, true));

@ -9,7 +9,7 @@ namespace llarp
{
namespace dht
{
struct RCNode
struct RCNode : public util::IStateful
{
RouterContact rc;
Key_t ID;
@ -23,6 +23,12 @@ namespace llarp
{
}
void
ExtractStatus(util::StatusObject& obj) const override
{
obj.PutInt("lastUpdated", rc.last_updated);
}
bool
operator<(const RCNode& other) const
{
@ -30,7 +36,7 @@ namespace llarp
}
};
struct ISNode
struct ISNode : public util::IStateful
{
service::IntroSet introset;
@ -46,6 +52,24 @@ namespace llarp
introset.A.CalculateAddress(ID.as_array());
}
void
ExtractStatus(util::StatusObject& obj) const override
{
obj.PutInt("timestamp", introset.T);
std::vector< util::StatusObject > introsObjs;
for(const auto intro : introset.I)
{
util::StatusObject introObj;
introObj.PutString("router", intro.router.ToHex());
introObj.PutInt("expiresAt", intro.expiresAt);
introObj.PutInt("latency", intro.latency);
introObj.PutInt("version", intro.version);
introsObjs.emplace_back(introObj);
}
obj.PutObjectArray("intros", introsObjs);
}
bool
operator<(const ISNode& other) const
{

@ -31,6 +31,26 @@ namespace llarp
return true;
}
void
PublishServiceJob::ExtractStatus(util::StatusObject &obj) const
{
obj.PutString("target", I.A.Name());
obj.PutInt("S", S);
util::StatusObject introsetObj;
I.ExtractStatus(introsetObj);
obj.PutObject("introset", introsetObj);
std::vector< std::string > dontTellObj;
for(const auto &key : dontTell)
dontTellObj.emplace_back(key.ToHex());
obj.PutStringArray("exclude", dontTellObj);
util::StatusObject whoaskedTx;
whoaskedTx.PutInt("txid", whoasked.txid);
whoaskedTx.PutString("node", whoasked.node.ToHex());
obj.PutObject("whoasked", whoaskedTx);
}
void
PublishServiceJob::Start(const TXOwner &peer)
{

@ -34,6 +34,9 @@ namespace llarp
return false;
}
void
ExtractStatus(util::StatusObject &obj) const override;
void
DoNextRequest(const Key_t &) override
{

@ -25,6 +25,31 @@ namespace llarp
return false;
}
void
ExtractStatus(util::StatusObject &obj) const override
{
std::vector< util::StatusObject > foundObjs;
for(const auto &found : valuesFound)
{
util::StatusObject foundObj;
found.ExtractStatus(foundObj);
foundObjs.emplace_back(foundObj);
}
obj.PutObjectArray("found", foundObjs);
util::StatusObject txownerObj;
txownerObj.PutInt("txid", whoasked.txid);
txownerObj.PutString("node", whoasked.node.ToHex());
obj.PutObject("whoasked", txownerObj);
std::vector< std::string > asked;
for(const auto &peer : peersAsked)
asked.emplace_back(peer.ToHex());
obj.PutStringArray("asked", asked);
obj.PutString("target", target.ToHex());
}
void
DoNextRequest(const Key_t &) override
{

@ -72,24 +72,50 @@ namespace llarp
ask);
}
}
void
ServiceAddressLookup::SendReply()
ServiceAddressLookup::ExtractStatus(util::StatusObject &obj) const
{
if(handleResult)
std::vector< util::StatusObject > foundObjs;
for(const auto &found : valuesFound)
{
handleResult(valuesFound);
util::StatusObject introsetObj;
found.ExtractStatus(introsetObj);
foundObjs.emplace_back(introsetObj);
}
obj.PutObjectArray("found", foundObjs);
util::StatusObject txownerObj;
txownerObj.PutInt("txid", whoasked.txid);
txownerObj.PutString("node", whoasked.node.ToHex());
obj.PutObject("whoasked", txownerObj);
std::vector< std::string > asked;
for(const auto &peer : peersAsked)
asked.emplace_back(peer.ToHex());
obj.PutStringArray("asked", asked);
obj.PutString("target", target.ToHex());
}
void
ServiceAddressLookup::SendReply()
{
// get newest introset
if(valuesFound.size())
{
llarp::service::IntroSet found;
for(const auto &introset : valuesFound)
{
if(found.OtherIsNewer(introset))
found = introset;
}
valuesFound.clear();
valuesFound.emplace_back(found);
}
if(handleResult)
{
handleResult(valuesFound);
}
parent->DHTSendTo(whoasked.node.as_array(),
new GotIntroMessage(valuesFound, whoasked.txid));
}

@ -34,6 +34,9 @@ namespace llarp
void
DoNextRequest(const Key_t &ask) override;
void
ExtractStatus(util::StatusObject &obj) const override;
virtual void
SendReply() override;
};

@ -30,6 +30,30 @@ namespace llarp
new FindIntroMessage(target, peer.txid, R));
}
void
TagLookup::ExtractStatus(util::StatusObject &obj) const
{
std::vector< util::StatusObject > foundObjs;
for(const auto &found : valuesFound)
{
util::StatusObject introsetObj;
found.ExtractStatus(introsetObj);
foundObjs.emplace_back(introsetObj);
}
obj.PutObjectArray("found", foundObjs);
util::StatusObject txownerObj;
txownerObj.PutInt("txid", whoasked.txid);
txownerObj.PutString("node", whoasked.node.ToHex());
obj.PutObject("whoasked", txownerObj);
std::vector< std::string > asked;
for(const auto &peer : peersAsked)
asked.emplace_back(peer.ToHex());
obj.PutStringArray("asked", asked);
obj.PutString("target", target.ToString());
}
void
TagLookup::SendReply()
{

@ -30,6 +30,9 @@ namespace llarp
return false;
}
void
ExtractStatus(util::StatusObject &obj) const override;
void
DoNextRequest(const Key_t &) override
{

@ -4,6 +4,7 @@
#include <dht/key.hpp>
#include <dht/txowner.hpp>
#include <util/logger.hpp>
#include <util/status.hpp>
#include <set>
#include <vector>
@ -15,7 +16,7 @@ namespace llarp
struct AbstractContext;
template < typename K, typename V >
struct TX
struct TX : public util::IStateful
{
K target;
AbstractContext* parent;
@ -37,6 +38,11 @@ namespace llarp
bool
AskNextPeer(const Key_t& prevPeer, const std::unique_ptr< Key_t >& next);
virtual void
ExtractStatus(util::StatusObject&) const override
{
}
virtual bool
Validate(const V& value) const = 0;

@ -5,6 +5,7 @@
#include <dht/txowner.hpp>
#include <util/logger.hpp>
#include <util/time.hpp>
#include <util/status.hpp>
#include <memory>
#include <unordered_map>
@ -15,7 +16,7 @@ namespace llarp
{
template < typename K, typename V, typename K_Hash,
llarp_time_t requestTimeoutMS = 5000UL >
struct TXHolder
struct TXHolder : public util::IStateful
{
using TXPtr = std::unique_ptr< TX< K, V > >;
// tx who are waiting for a reply for each key
@ -28,6 +29,54 @@ namespace llarp
const TX< K, V >*
GetPendingLookupFrom(const TXOwner& owner) const;
void
ExtractStatus(util::StatusObject& obj) const override
{
std::vector< util::StatusObject > txObjs, timeoutsObjs, waitingObjs;
{
auto itr = tx.begin();
while(itr != tx.end())
{
util::StatusObject txObj, txOwnerObj, txSuperObj;
itr->second->ExtractStatus(txObj);
txOwnerObj.PutInt("txid", itr->first.txid);
txOwnerObj.PutString("node", itr->first.node.ToHex());
txSuperObj.PutObject("tx", txObj);
txSuperObj.PutObject("owner", txOwnerObj);
txObjs.emplace_back(txSuperObj);
++itr;
}
}
obj.PutObjectArray("tx", txObjs);
{
auto itr = timeouts.begin();
while(itr != timeouts.end())
{
util::StatusObject timeoutObj;
timeoutObj.PutInt("time", itr->second);
timeoutObj.PutString("target", itr->first.ToHex());
timeoutsObjs.emplace_back(timeoutObj);
++itr;
}
}
obj.PutObjectArray("timeouts", timeoutsObjs);
{
auto itr = waiting.begin();
while(itr != waiting.end())
{
util::StatusObject waitingObj, txOwnerObj;
txOwnerObj.PutInt("txid", itr->second.txid);
txOwnerObj.PutString("node", itr->second.node.ToHex());
waitingObj.PutObject("whoasked", txOwnerObj);
waitingObj.PutString("target", itr->first.ToHex());
waitingObjs.emplace_back(waitingObj);
++itr;
}
}
obj.PutObjectArray("waiting", waitingObjs);
}
bool
HasLookupFor(const K& target) const
{

@ -46,6 +46,19 @@ namespace llarp
}
}
void
Context::ExtractStatus(util::StatusObject& obj) const
{
auto itr = m_Exits.begin();
while(itr != m_Exits.end())
{
util::StatusObject sobj;
itr->second->ExtractStatus(sobj);
obj.PutObject(itr->first.c_str(), sobj);
++itr;
}
}
void
Context::CalculateExitTraffic(TrafficStats& stats)
{

@ -11,7 +11,7 @@ namespace llarp
namespace exit
{
/// owner of all the exit endpoints
struct Context
struct Context : public util::IStateful
{
using Config_t = std::unordered_multimap< std::string, std::string >;
@ -24,6 +24,9 @@ namespace llarp
void
ClearAllEndpoints();
void
ExtractStatus(util::StatusObject &obj) const;
/// send close to all exit sessions and remove all sessions
void
Stop();

@ -31,6 +31,21 @@ namespace llarp
m_Parent->RemoveExit(this);
}
void
Endpoint::ExtractStatus(util::StatusObject& obj) const
{
obj.PutString("identity", m_remoteSignKey.ToHex());
obj.PutString("ip", m_IP.ToString());
obj.PutInt("txRate", m_TxRate);
obj.PutInt("rxRate", m_RxRate);
obj.PutInt("createdAt", createdAt);
auto now = m_Parent->Now();
obj.PutBool("exiting", !m_RewriteSource);
obj.PutBool("looksDead", LooksDead(now));
obj.PutBool("expiresSoon", ExpiresSoon(now));
obj.PutBool("expired", IsExpired(now));
}
bool
Endpoint::UpdateLocalPath(const llarp::PathID_t& nextPath)
{

@ -17,7 +17,7 @@ namespace llarp
namespace exit
{
/// persistant exit state for 1 identity on the exit node
struct Endpoint
struct Endpoint : public util::IStateful
{
static constexpr size_t MaxUpstreamQueueSize = 256;
@ -31,6 +31,10 @@ namespace llarp
void
Close();
/// implement istateful
void
ExtractStatus(util::StatusObject& obj) const override;
/// return true if we are expired right now
bool
IsExpired(llarp_time_t now) const;

@ -24,6 +24,15 @@ namespace llarp
{
}
void
BaseSession::ExtractStatus(util::StatusObject& obj) const
{
path::Builder::ExtractStatus(obj);
obj.PutInt("lastExitUse", m_LastUse);
auto pub = m_ExitIdentity.toPublic();
obj.PutString("exitIdentity", pub.ToString());
}
bool
BaseSession::LoadIdentityFromFile(const char* fname)
{

@ -25,6 +25,9 @@ namespace llarp
virtual ~BaseSession();
void
ExtractStatus(util::StatusObject& obj) const override;
bool
SelectHop(llarp_nodedb* db, const RouterContact& prev, RouterContact& cur,
size_t hop, llarp::path::PathRole roles) override;

@ -42,6 +42,25 @@ namespace llarp
{
}
void
ExitEndpoint::ExtractStatus(util::StatusObject &obj) const
{
obj.PutBool("permitExit", m_PermitExit);
std::vector< util::StatusObject > activeObjs;
{
auto itr = m_ActiveExits.begin();
while(itr != m_ActiveExits.end())
{
util::StatusObject sessionObj;
itr->second->ExtractStatus(sessionObj);
activeObjs.emplace_back(sessionObj);
++itr;
}
}
obj.PutString("ip", m_IfAddr.ToString());
obj.PutObjectArray("exitSessions", activeObjs);
}
bool
ExitEndpoint::ShouldHookDNSMessage(const dns::Message &msg) const
{

@ -11,7 +11,7 @@ namespace llarp
struct Router;
namespace handlers
{
struct ExitEndpoint : public dns::IQueryHandler
struct ExitEndpoint : public dns::IQueryHandler, public util::IStateful
{
ExitEndpoint(const std::string& name, Router* r);
~ExitEndpoint();
@ -25,6 +25,9 @@ namespace llarp
std::string
Name() const;
void
ExtractStatus(util::StatusObject& obj) const override;
bool
ShouldHookDNSMessage(const dns::Message& msg) const override;

@ -53,6 +53,38 @@ namespace llarp
tunif.recvpkt = &tunifRecvPkt;
}
void
TunEndpoint::ExtractStatus(util::StatusObject &obj) const
{
service::Endpoint::ExtractStatus(obj);
obj.PutString("ifaddr", m_OurRange.ToString());
std::vector< std::string > resolvers;
for(const auto &addr : m_UpstreamResolvers)
resolvers.emplace_back(addr.ToString());
obj.PutStringArray("ustreamResolvers", resolvers);
obj.PutString("localResolver", m_LocalResolverAddr.ToString());
util::StatusObject ips;
for(const auto &item : m_IPActivity)
{
util::StatusObject ipObj;
ipObj.PutInt("lastActive", item.second);
std::string remoteStr;
AlignedBuffer< 32 > addr = m_IPToAddr.at(item.first);
if(m_SNodes.at(addr))
remoteStr = RouterID(addr.as_array()).ToString();
else
remoteStr = service::Address(addr.as_array()).ToString();
ipObj.PutString("remote", remoteStr);
std::string ipaddr = item.first.ToString();
ips.PutObject(ipaddr.c_str(), ipObj);
}
obj.PutObject("addrs", ips);
obj.PutString("ourIP", m_OurIP.ToString());
obj.PutString("nextIP", m_NextIP.ToString());
obj.PutString("maxIP", m_MaxIP.ToString());
}
bool
TunEndpoint::SetOption(const std::string &k, const std::string &v)
{

@ -30,6 +30,9 @@ namespace llarp
virtual void
Tick(llarp_time_t now) override;
void
ExtractStatus(util::StatusObject& obj) const override;
bool
ShouldHookDNSMessage(const dns::Message& msg) const override;

@ -7,6 +7,7 @@
#include <util/logger.hpp>
#include <util/mem.hpp>
#include <util/string_view.hpp>
#include <util/bits.hpp>
#include <functional>
#include <stdlib.h> // for itoa
@ -71,7 +72,14 @@ namespace llarp
friend std::ostream&
operator<<(std::ostream& out, const IPRange& a)
{
return out << a.addr << "/" << a.netmask_bits;
return out << a.ToString();
}
std::string
ToString() const
{
return addr.ToString() + "/"
+ std::to_string(llarp::bits::count_bits(netmask_bits.h));
}
};

@ -53,6 +53,15 @@ namespace llarp
return out;
}
std::string 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;
}
struct Hash
{
inline size_t

@ -155,26 +155,24 @@ 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
@ -191,14 +189,13 @@ 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*
@ -438,6 +435,55 @@ namespace llarp
_status = st;
}
void
Path::ExtractStatus(util::StatusObject& obj) const
{
std::vector< util::StatusObject > subobj;
for(const auto& hop : hops)
{
util::StatusObject hopobj;
hopobj.PutString("txid", hop.txID.ToHex());
hopobj.PutString("rxid", hop.rxID.ToHex());
hopobj.PutString("router", hop.rc.pubkey.ToString());
hopobj.PutInt("lifetime", hop.lifetime);
subobj.emplace_back(hopobj);
}
obj.PutObjectArray("hops", subobj);
util::StatusObject introObj;
intro.ExtractStatus(introObj);
obj.PutObject("intro", introObj);
switch(_status)
{
case ePathBuilding:
obj.PutString("status", "building");
break;
case ePathEstablished:
obj.PutString("status", "established");
break;
case ePathTimeout:
obj.PutString("status", "timeout");
break;
case ePathExpired:
obj.PutString("status", "expired");
break;
default:
obj.PutString("status", "unknown");
break;
}
obj.PutInt("lastRecvMsg", m_LastRecvMessage);
obj.PutInt("lastLatencyTest", m_LastLatencyTestTime);
obj.PutInt("buildStarted", buildStarted);
obj.PutBool("ready", IsReady());
obj.PutBool("hasExit", SupportsAnyRoles(ePathRoleExit));
auto now = llarp::time_now_ms();
obj.PutBool("expired", Expired(now));
obj.PutBool("expiresSoon", ExpiresSoon(now));
obj.PutInt("expiresAt", ExpireTime());
}
void
Path::Tick(llarp_time_t now, llarp::Router* r)
{

@ -291,7 +291,9 @@ namespace llarp
};
/// A path we made
struct Path : public IHopHandler, public llarp::routing::IMessageHandler
struct Path : public IHopHandler,
public llarp::routing::IMessageHandler,
public util::IStateful
{
using BuildResultHookFunc = std::function< void(Path*) >;
using CheckForDeadFunc = std::function< bool(Path*, llarp_time_t) >;
@ -318,6 +320,9 @@ namespace llarp
Path(const std::vector< RouterContact >& routers, PathSet* parent,
PathRole startingRoles);
void
ExtractStatus(util::StatusObject& obj) const override;
PathRole
Role() const
{

@ -184,6 +184,21 @@ namespace llarp
router->paths.RemovePathBuilder(this);
}
void
Builder::ExtractStatus(util::StatusObject& obj) const
{
obj.PutInt("keygens", keygens.load());
obj.PutInt("numHops", numHops);
obj.PutInt("numPaths", m_NumPaths);
std::vector< util::StatusObject > pathObjs;
ForEachPath([&pathObjs](const Path* p) {
util::StatusObject pobj;
p->ExtractStatus(pobj);
pathObjs.emplace_back(pobj);
});
obj.PutObjectArray("paths", pathObjs);
}
bool
Builder::SelectHop(llarp_nodedb* db, const RouterContact& prev,
RouterContact& cur, size_t hop, PathRole roles)

@ -2,6 +2,8 @@
#define LLARP_PATHBUILDER_HPP_
#include <path/pathset.hpp>
#include <util/status.hpp>
#include <atomic>
struct llarp_dht_context;
@ -13,7 +15,7 @@ namespace llarp
// milliseconds waiting between builds on a path
constexpr llarp_time_t MIN_PATH_BUILD_INTERVAL = 5 * 1000;
struct Builder : public PathSet
struct Builder : public PathSet, public util::IStateful
{
protected:
/// flag for PathSet::Stop()
@ -36,6 +38,9 @@ namespace llarp
virtual ~Builder();
virtual void
ExtractStatus(util::StatusObject& obj) const override;
virtual bool
SelectHop(llarp_nodedb* db, const RouterContact& prev, RouterContact& cur,
size_t hop, PathRole roles) override;

@ -7,6 +7,7 @@
#include <service/IntroSet.hpp>
#include <service/lookup.hpp>
#include <util/time.hpp>
#include <util/status.hpp>
#include <functional>
#include <list>
@ -209,6 +210,18 @@ namespace llarp
}
}
void
ForEachPath(std::function< void(const Path*) > visit) const
{
Lock_t lock(m_PathsMutex);
auto itr = m_Paths.begin();
while(itr != m_Paths.end())
{
visit(itr->second);
++itr;
}
}
private:
using PathInfo_t = std::pair< RouterID, PathID_t >;

@ -237,6 +237,18 @@ namespace llarp
llarp_dht_context_free(_dht);
}
void
Router::ExtractStatus(util::StatusObject &obj) const
{
util::StatusObject dhtObj, exitObj, hsObj;
_dht->impl.ExtractStatus(dhtObj);
obj.PutObject("dht", dhtObj);
hiddenServiceContext.ExtractStatus(hsObj);
obj.PutObject("services", hsObj);
exitContext.ExtractStatus(exitObj);
obj.PutObject("exit", exitObj);
}
bool
Router::HandleRecvLinkMessageBuffer(llarp::ILinkSession *session,
const llarp_buffer_t &buf)

@ -20,6 +20,7 @@
#include <util/fs.hpp>
#include <util/logic.hpp>
#include <util/mem.hpp>
#include <util/status.hpp>
#include <util/str.hpp>
#include <util/threadpool.hpp>
@ -113,7 +114,7 @@ namespace llarp
const std::vector< llarp::RouterContact > &results) = 0;
};
struct Router final : public AbstractRouter
struct Router final : public AbstractRouter, public util::IStateful
{
bool ready;
// transient iwp encryption key
@ -152,6 +153,9 @@ namespace llarp
return _dht;
}
void
ExtractStatus(util::StatusObject &obj) const override;
Crypto *
crypto() const override
{

@ -151,6 +151,16 @@ namespace llarp
last_updated = 0;
}
void
RouterContact::ExtractStatus(util::StatusObject &obj) const
{
obj.PutInt("lastUpdated", last_updated);
obj.PutBool("exit", IsExit());
obj.PutBool("publicRouter", IsPublicRouter());
if(HasNick())
obj.PutString("nickname", Nick());
}
bool
RouterContact::DecodeKey(const llarp_buffer_t &key, llarp_buffer_t *buf)
{

@ -7,6 +7,7 @@
#include <net/exit_info.hpp>
#include <util/aligned.hpp>
#include <util/bencode.hpp>
#include <util/status.hpp>
#include <functional>
#include <vector>
@ -56,7 +57,7 @@ namespace llarp
};
/// RouterContact
struct RouterContact final : public IBEncodeMessage
struct RouterContact final : public IBEncodeMessage, public util::IStateful
{
/// for unit tests
static bool IgnoreBogons;
@ -98,6 +99,9 @@ namespace llarp
uint64_t last_updated = 0;
void
ExtractStatus(util::StatusObject &obj) const override;
bool
BEncode(llarp_buffer_t *buf) const override;

@ -217,6 +217,15 @@ namespace llarp
{
}
bool
DumpState(Response& resp) const
{
util::StatusObject dump;
router->ExtractStatus(dump);
resp.AddMember("result", dump.Impl, resp.GetAllocator());
return true;
}
bool
ListExitLevels(Response& resp) const
{
@ -280,6 +289,10 @@ namespace llarp
{
return ListExitLevels(response);
}
else if(method == "llarp.admin.dumpstate")
{
return DumpState(response);
}
return false;
}
};

@ -8,6 +8,15 @@ namespace llarp
{
}
void
Introduction::ExtractStatus(util::StatusObject& obj) const
{
obj.PutString("router", router.ToHex());
obj.PutInt("expiresAt", expiresAt);
obj.PutInt("latency", latency);
obj.PutInt("version", version);
}
bool
Introduction::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf)
{

@ -4,6 +4,7 @@
#include <crypto/types.hpp>
#include <path/path_types.hpp>
#include <util/bencode.hpp>
#include <util/status.hpp>
#include <iostream>
@ -11,7 +12,8 @@ namespace llarp
{
namespace service
{
struct Introduction final : public llarp::IBEncodeMessage
struct Introduction final : public llarp::IBEncodeMessage,
public util::IStateful
{
llarp::PubKey router;
llarp::PathID_t pathID;
@ -29,6 +31,9 @@ namespace llarp
expiresAt = other.expiresAt;
}
void
ExtractStatus(util::StatusObject& obj) const override;
bool
IsExpired(llarp_time_t now) const
{

@ -12,6 +12,22 @@ namespace llarp
delete W;
}
void
IntroSet::ExtractStatus(util::StatusObject& obj) const
{
std::vector< util::StatusObject > introsObjs;
for(const auto& intro : I)
{
util::StatusObject introObj;
intro.ExtractStatus(introObj);
introsObjs.emplace_back(introObj);
}
obj.PutObjectArray("intros", introsObjs);
if(!topic.IsZero())
obj.PutString("topic", topic.ToString());
obj.PutInt("published", T);
}
bool
IntroSet::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf)
{

@ -8,6 +8,7 @@
#include <service/tag.hpp>
#include <util/bencode.hpp>
#include <util/time.hpp>
#include <util/status.hpp>
#include <algorithm>
#include <functional>
@ -23,8 +24,12 @@ namespace llarp
constexpr std::size_t MAX_INTROSET_SIZE = 4096;
// 10 seconds clock skew permitted for introset expiration
constexpr llarp_time_t MAX_INTROSET_TIME_DELTA = (10 * 1000);
struct IntroSet final : public llarp::IBEncodeMessage
struct IntroSet final : public llarp::IBEncodeMessage,
public util::IStateful
{
void
ExtractStatus(util::StatusObject& obj) const override;
ServiceInfo A;
std::vector< Introduction > I;
PQPubKey K;

@ -30,6 +30,19 @@ namespace llarp
return true;
}
void
Context::ExtractStatus(util::StatusObject &obj) const
{
auto itr = m_Endpoints.begin();
while(itr != m_Endpoints.end())
{
util::StatusObject sobj;
itr->second->ExtractStatus(sobj);
obj.PutObject(itr->first.c_str(), sobj);
++itr;
}
}
void
Context::ForEachService(
std::function< bool(const std::string &,

@ -13,7 +13,7 @@ namespace llarp
namespace service
{
/// holds all the hidden service endpoints we own
struct Context
struct Context : public util::IStateful
{
Context(llarp::Router *r);
~Context();
@ -25,6 +25,9 @@ namespace llarp
bool
StopAll();
void
ExtractStatus(util::StatusObject &obj) const override;
bool
hasEndpoints();

@ -144,6 +144,84 @@ namespace llarp
}
}
void
Endpoint::ExtractStatus(util::StatusObject& obj) const
{
path::Builder::ExtractStatus(obj);
obj.PutString("identity", m_Identity.pub.Addr().ToString());
obj.PutInt("lastPublished", m_LastPublish);
obj.PutInt("lastPublishAttempt", m_LastPublishAttempt);
util::StatusObject introsetObj;
m_IntroSet.ExtractStatus(introsetObj);
obj.PutObject("introset", introsetObj);
if(!m_Tag.IsZero())
obj.PutString("tag", m_Tag.ToString());
std::vector< util::StatusObject > remoteSessions, deadSessions,
snodeSessions, lookups;
{
auto itr = m_RemoteSessions.begin();
while(itr != m_RemoteSessions.end())
{
util::StatusObject sobj;
itr->second->ExtractStatus(sobj);
remoteSessions.emplace_back(sobj);
++itr;
}
}
obj.PutObjectArray("remoteSessions", remoteSessions);
{
auto itr = m_DeadSessions.begin();
while(itr != m_DeadSessions.end())
{
util::StatusObject sobj;
itr->second->ExtractStatus(sobj);
deadSessions.emplace_back(sobj);
++itr;
}
}
obj.PutObjectArray("deadSessions", deadSessions);
{
auto itr = m_SNodeSessions.begin();
while(itr != m_SNodeSessions.end())
{
util::StatusObject sobj;
itr->second->ExtractStatus(sobj);
snodeSessions.emplace_back(sobj);
++itr;
}
}
obj.PutObjectArray("snodeSessions", snodeSessions);
{
auto itr = m_PendingLookups.begin();
while(itr != m_PendingLookups.end())
{
util::StatusObject sobj;
itr->second->ExtractStatus(sobj);
lookups.emplace_back(sobj);
++itr;
}
}
obj.PutObjectArray("lookups", lookups);
util::StatusObject sessionObj;
{
auto itr = m_Sessions.begin();
while(itr != m_Sessions.end())
{
util::StatusObject sobj;
itr->second.ExtractStatus(sobj);
std::string k = itr->first.ToHex();
sessionObj.PutObject(k.c_str(), sobj);
++itr;
}
}
obj.PutObject("converstations", sessionObj);
}
void
Endpoint::Tick(llarp_time_t now)
{
@ -233,12 +311,13 @@ namespace llarp
continue;
std::array< byte_t, 1024 > tmp = {0};
llarp_buffer_t buf(tmp);
if(!SendToServiceOrQueue(introset.A.Addr().data(), buf,
eProtocolText))
{
if(SendToServiceOrQueue(introset.A.Addr().data(), buf, eProtocolText))
llarp::LogInfo(Name(), " send message to ", introset.A.Addr(),
" for tag ", tag.ToString());
else
llarp::LogWarn(Name(), " failed to send/queue data to ",
introset.A.Addr(), " for tag ", tag.ToString());
}
}
itr->second.Expire(now);
if(itr->second.ShouldRefresh(now))

@ -40,6 +40,9 @@ namespace llarp
Endpoint(const std::string& nickname, llarp::Router* r, Context* parent);
~Endpoint();
virtual void
ExtractStatus(util::StatusObject& obj) const override;
void
SetHandler(IDataHandler* h);
@ -532,13 +535,24 @@ namespace llarp
/// on initialize functions
std::list< std::function< bool(void) > > m_OnInit;
struct Session
struct Session : public util::IStateful
{
SharedSecret sharedKey;
ServiceInfo remote;
Introduction intro;
llarp_time_t lastUsed = 0;
uint64_t seqno = 0;
void
ExtractStatus(util::StatusObject& obj) const override
{
obj.PutInt("lastUsed", lastUsed);
obj.PutString("remote", remote.Addr().ToString());
obj.PutInt("seqno", seqno);
util::StatusObject introObj;
intro.ExtractStatus(introObj);
obj.PutObject("intro", introObj);
};
};
/// sessions

@ -20,7 +20,7 @@ namespace llarp
constexpr size_t MaxConcurrentLookups = size_t(4);
struct IServiceLookup
struct IServiceLookup : public util::IStateful
{
IServiceLookup() = delete;
virtual ~IServiceLookup(){};
@ -55,6 +55,17 @@ namespace llarp
const std::string name;
RouterID endpoint;
void
ExtractStatus(util::StatusObject& obj) const override
{
auto now = llarp::time_now_ms();
obj.PutInt("txid", txid);
obj.PutString("endpoint", endpoint.ToHex());
obj.PutString("name", name);
obj.PutBool("timedOut", IsTimedOut(now));
obj.PutInt("createdAt", m_created);
}
protected:
IServiceLookup(ILookupHolder* parent, uint64_t tx,
const std::string& name);

@ -0,0 +1,128 @@
#include <util/status.hpp>
namespace llarp
{
namespace util
{
StatusObject::StatusObject()
{
#ifdef USE_ABYSS
Impl.SetObject();
#endif
}
StatusObject::StatusObject(const StatusObject& other)
{
#ifdef USE_ABYSS
Impl.SetObject();
Impl.CopyFrom(other.Impl, Impl.GetAllocator());
#else
(void)other;
#endif
}
StatusObject::~StatusObject()
{
}
void
StatusObject::PutBool(const char* name, bool val)
{
#ifdef USE_ABYSS
Value_t v;
v.SetBool(val);
Value_t k(name, Impl.GetAllocator());
Impl.AddMember(k, v, Impl.GetAllocator());
#else
(void)name;
(void)val;
#endif
}
void
StatusObject::PutInt(const char* name, uint64_t val)
{
#ifdef USE_ABYSS
Value_t v;
v.SetInt(val);
Value_t k(name, Impl.GetAllocator());
Impl.AddMember(k, v, Impl.GetAllocator());
#else
(void)name;
(void)val;
#endif
}
void
StatusObject::PutObject(const char* name, const StatusObject& val)
{
#ifdef USE_ABYSS
Value_t v;
v.SetObject();
v.CopyFrom(val.Impl, Impl.GetAllocator());
Value_t k(name, Impl.GetAllocator());
Impl.AddMember(k, v, Impl.GetAllocator());
#else
(void)name;
(void)val;
#endif
}
void
StatusObject::PutObjectArray(const char* name,
const std::vector< StatusObject >& arr)
{
#ifdef USE_ABYSS
Value_t v;
v.SetArray();
for(const auto& obj : arr)
{
Value_t i;
i.SetObject();
i.CopyFrom(obj.Impl, Impl.GetAllocator());
v.PushBack(i, Impl.GetAllocator());
}
Value_t k(name, Impl.GetAllocator());
Impl.AddMember(k, v, Impl.GetAllocator());
#else
(void)name;
(void)val;
#endif
}
void
StatusObject::PutStringArray(const char* name,
const std::vector< std::string >& arr)
{
#ifdef USE_ABYSS
Value_t v;
v.SetArray();
for(const auto& str : arr)
{
Value_t i;
i.SetString(str.c_str(), Impl.GetAllocator());
v.PushBack(i, Impl.GetAllocator());
}
Value_t k(name, Impl.GetAllocator());
Impl.AddMember(k, v, Impl.GetAllocator());
#else
(void)name;
(void)val;
#endif
}
void
StatusObject::PutString(const char* name, const std::string& val)
{
#ifdef USE_ABYSS
Value_t v;
v.SetString(val.c_str(), Impl.GetAllocator());
Value_t k(name, Impl.GetAllocator());
Impl.AddMember(k, v, Impl.GetAllocator());
#else
(void)name;
(void)val;
#endif
}
} // namespace util
} // namespace llarp

@ -0,0 +1,62 @@
#ifndef LLARP_UTIL_STATUS_HPP
#define LLARP_UTIL_STATUS_HPP
#ifdef USE_ABYSS
#include <abyss/json.hpp>
#endif
#include <vector>
namespace llarp
{
namespace util
{
#ifdef USE_ABYSS
using StatusObject_Impl = ::abyss::json::Document;
using Value_t = ::abyss::json::Value;
#else
struct StatusObject_Impl
{
};
#endif
struct StatusObject
{
StatusObject();
~StatusObject();
StatusObject(StatusObject&&) = delete;
StatusObject(const StatusObject& other);
void
PutInt(const char* name, uint64_t val);
void
PutString(const char* name, const std::string& val);
void
PutBool(const char* name, bool val);
void
PutObject(const char* name, const StatusObject& obj);
void
PutStringArray(const char* name, const std::vector< std::string >& arr);
void
PutObjectArray(const char* name, const std::vector< StatusObject >& arr);
StatusObject_Impl Impl;
};
/// an entity that has a status that can be extracted
struct IStateful
{
virtual ~IStateful(){};
virtual void
ExtractStatus(StatusObject& state) const = 0;
};
} // namespace util
} // namespace llarp
#endif
Loading…
Cancel
Save