2019-01-22 01:14:02 +00:00
|
|
|
#ifndef LLARP_DHT_TX
|
|
|
|
#define LLARP_DHT_TX
|
|
|
|
|
|
|
|
#include <dht/key.hpp>
|
|
|
|
#include <dht/txowner.hpp>
|
|
|
|
#include <util/logger.hpp>
|
2019-02-08 19:43:25 +00:00
|
|
|
#include <util/status.hpp>
|
2019-01-22 01:14:02 +00:00
|
|
|
|
|
|
|
#include <set>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
namespace llarp
|
|
|
|
{
|
|
|
|
namespace dht
|
|
|
|
{
|
2019-01-24 01:31:02 +00:00
|
|
|
struct AbstractContext;
|
2019-01-22 01:14:02 +00:00
|
|
|
|
|
|
|
template < typename K, typename V >
|
2019-02-08 19:43:25 +00:00
|
|
|
struct TX : public util::IStateful
|
2019-01-22 01:14:02 +00:00
|
|
|
{
|
|
|
|
K target;
|
2019-01-24 01:31:02 +00:00
|
|
|
AbstractContext* parent;
|
2019-01-22 01:14:02 +00:00
|
|
|
std::set< Key_t > peersAsked;
|
|
|
|
std::vector< V > valuesFound;
|
|
|
|
TXOwner whoasked;
|
|
|
|
|
2019-01-24 01:31:02 +00:00
|
|
|
TX(const TXOwner& asker, const K& k, AbstractContext* p)
|
|
|
|
: target(k), parent(p), whoasked(asker)
|
2019-01-22 01:14:02 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ~TX(){};
|
|
|
|
|
2019-01-22 23:50:26 +00:00
|
|
|
void
|
|
|
|
OnFound(const Key_t& askedPeer, const V& value);
|
|
|
|
|
|
|
|
/// return true if we want to persist this tx
|
|
|
|
bool
|
|
|
|
AskNextPeer(const Key_t& prevPeer, const std::unique_ptr< Key_t >& next);
|
|
|
|
|
2019-02-11 17:14:43 +00:00
|
|
|
util::StatusObject
|
|
|
|
ExtractStatus() const override
|
2019-02-08 19:43:25 +00:00
|
|
|
{
|
2019-02-11 17:14:43 +00:00
|
|
|
util::StatusObject obj{{"whoasked", whoasked.ExtractStatus()},
|
|
|
|
{"target", target.ToHex()}};
|
|
|
|
std::vector< util::StatusObject > foundObjs;
|
|
|
|
std::transform(valuesFound.begin(), valuesFound.end(),
|
|
|
|
std::back_inserter(foundObjs),
|
|
|
|
[](const auto& item) -> util::StatusObject {
|
|
|
|
return item.ExtractStatus();
|
|
|
|
});
|
|
|
|
|
|
|
|
obj.Put("found", foundObjs);
|
|
|
|
std::vector< std::string > asked;
|
|
|
|
std::transform(
|
|
|
|
peersAsked.begin(), peersAsked.end(), std::back_inserter(asked),
|
|
|
|
[](const auto& item) -> std::string { return item.ToHex(); });
|
|
|
|
obj.Put("asked", asked);
|
|
|
|
return obj;
|
2019-02-08 19:43:25 +00:00
|
|
|
}
|
|
|
|
|
2019-01-22 01:14:02 +00:00
|
|
|
virtual bool
|
|
|
|
Validate(const V& value) const = 0;
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
Start(const TXOwner& peer) = 0;
|
|
|
|
|
|
|
|
virtual bool
|
|
|
|
GetNextPeer(Key_t& next, const std::set< Key_t >& exclude) = 0;
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
DoNextRequest(const Key_t& peer) = 0;
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
SendReply() = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
template < typename K, typename V >
|
|
|
|
inline void
|
2019-01-22 23:50:26 +00:00
|
|
|
TX< K, V >::OnFound(const Key_t& askedPeer, const V& value)
|
2019-01-22 01:14:02 +00:00
|
|
|
{
|
|
|
|
peersAsked.insert(askedPeer);
|
|
|
|
if(Validate(value))
|
|
|
|
{
|
|
|
|
valuesFound.push_back(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template < typename K, typename V >
|
|
|
|
inline bool
|
|
|
|
TX< K, V >::AskNextPeer(const Key_t& prevPeer,
|
|
|
|
const std::unique_ptr< Key_t >& next)
|
|
|
|
{
|
|
|
|
peersAsked.insert(prevPeer);
|
|
|
|
Key_t peer;
|
|
|
|
if(next)
|
|
|
|
{
|
|
|
|
// explicit next peer provided
|
|
|
|
peer = *next;
|
|
|
|
}
|
|
|
|
else if(!GetNextPeer(peer, peersAsked))
|
|
|
|
{
|
|
|
|
// no more peers
|
2019-01-24 01:31:02 +00:00
|
|
|
llarp::LogInfo("no more peers for request asking for ", target);
|
2019-01-22 01:14:02 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Key_t targetKey{target};
|
|
|
|
if((prevPeer ^ targetKey) < (peer ^ targetKey))
|
|
|
|
{
|
|
|
|
// next peer is not closer
|
|
|
|
llarp::LogInfo("next peer ", peer, " is not closer to ", target,
|
|
|
|
" than ", prevPeer);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
peersAsked.insert(peer);
|
|
|
|
}
|
|
|
|
DoNextRequest(peer);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} // namespace dht
|
|
|
|
} // namespace llarp
|
|
|
|
|
|
|
|
#endif
|