From b037cf0ae4545e8ddf52e5a5ed9cece50b543bad Mon Sep 17 00:00:00 2001 From: Stephen Shelton Date: Fri, 24 Jul 2020 11:49:14 -0600 Subject: [PATCH] Handle get_peer_stats request's list of router ids --- llarp/peerstats/peer_db.cpp | 18 ++++++++++++++++++ llarp/peerstats/peer_db.hpp | 7 +++++++ llarp/rpc/lokid_rpc_client.cpp | 33 ++++++++++++++++++++++++++++++--- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/llarp/peerstats/peer_db.cpp b/llarp/peerstats/peer_db.cpp index 9d4fe50d2..3ca8d4328 100644 --- a/llarp/peerstats/peer_db.cpp +++ b/llarp/peerstats/peer_db.cpp @@ -156,6 +156,24 @@ namespace llarp return statsList; } + std::vector + PeerDb::listPeerStats(const std::vector& ids) const + { + std::lock_guard guard(m_statsLock); + + std::vector statsList; + statsList.reserve(ids.size()); + + for (const auto& id : ids) + { + const auto itr = m_peerStats.find(id); + if (itr != m_peerStats.end()) + statsList.push_back(itr->second); + } + + return statsList; + } + /// Assume we receive an RC at some point `R` in time which was signed at some point `S` in time /// and expires at some point `E` in time, as depicted below: /// diff --git a/llarp/peerstats/peer_db.hpp b/llarp/peerstats/peer_db.hpp index d7985e1bd..d5d4a1a05 100644 --- a/llarp/peerstats/peer_db.hpp +++ b/llarp/peerstats/peer_db.hpp @@ -90,6 +90,13 @@ namespace llarp std::vector listAllPeerStats() const; + /// Lists specific peer stats. + /// + /// @param peers is list of RouterIDs which are desired + /// @return a list of the requested peers. Peers not found will be omitted. + std::vector + listPeerStats(const std::vector& ids) const; + /// Handles a new gossiped RC, updating stats as needed. The database tracks the last /// advertised update time, so it knows whether this is a new RC or not. /// diff --git a/llarp/rpc/lokid_rpc_client.cpp b/llarp/rpc/lokid_rpc_client.cpp index 68c3498cc..e5cd8c6c7 100644 --- a/llarp/rpc/lokid_rpc_client.cpp +++ b/llarp/rpc/lokid_rpc_client.cpp @@ -1,5 +1,6 @@ #include +#include #include #include @@ -228,14 +229,40 @@ namespace llarp if (not m_Router->peerDb()) { LogWarn("HandleGetPeerStats called when router has no peerDb set up."); - throw std::runtime_error("Cannot handle get_peer_stats request when no peer db available"); + + // TODO: this can sometimes occur if lokid hits our API before we're done configuring + // (mostly an issue in a loopback testnet) + msg.send_reply("EAGAIN"); + return; } try { - // TODO: parse input, expect list of peers to query for + // msg.data[0] is expected to contain a bt list of router ids (in our preferred string + // format) + if (msg.data.empty()) + { + LogWarn("lokid requested peer stats with no request body"); + msg.send_reply("peer stats request requires list of router IDs"); + return; + } + + std::vector routerIdStrings; + lokimq::bt_deserialize(msg.data[0], routerIdStrings); + + std::vector routerIds; + routerIds.reserve(routerIdStrings.size()); + + for (const auto& routerIdString : routerIdStrings) + { + RouterID id; + if (not id.FromString(routerIdString)) + throw std::invalid_argument(stringify("Invalid router id: ", routerIdString)); + + routerIds.push_back(std::move(id)); + } - auto statsList = m_Router->peerDb()->listAllPeerStats(); + auto statsList = m_Router->peerDb()->listPeerStats(routerIds); int32_t bufSize = 256 + (statsList.size() * 1024); // TODO: tune this or allow to grow dynamically