2018-12-12 00:48:54 +00:00
|
|
|
#include <dht/context.hpp>
|
2019-01-14 21:46:07 +00:00
|
|
|
|
2019-01-22 01:14:02 +00:00
|
|
|
#include <dht/explorenetworkjob.hpp>
|
|
|
|
#include <dht/localrouterlookup.hpp>
|
|
|
|
#include <dht/localserviceaddresslookup.hpp>
|
|
|
|
#include <dht/localtaglookup.hpp>
|
2019-01-16 00:24:16 +00:00
|
|
|
#include <dht/messages/findrouter.hpp>
|
|
|
|
#include <dht/messages/gotintro.hpp>
|
2018-12-12 00:48:54 +00:00
|
|
|
#include <dht/messages/gotrouter.hpp>
|
2019-01-16 00:24:16 +00:00
|
|
|
#include <dht/messages/pubintro.hpp>
|
2019-01-19 18:16:40 +00:00
|
|
|
#include <dht/node.hpp>
|
2019-01-22 01:14:02 +00:00
|
|
|
#include <dht/publishservicejob.hpp>
|
|
|
|
#include <dht/recursiverouterlookup.hpp>
|
|
|
|
#include <dht/serviceaddresslookup.hpp>
|
|
|
|
#include <dht/taglookup.hpp>
|
2018-12-12 02:52:51 +00:00
|
|
|
#include <messages/dht_immediate.hpp>
|
2019-06-17 23:19:39 +00:00
|
|
|
#include <path/path_context.hpp>
|
2019-02-11 19:45:42 +00:00
|
|
|
#include <router/abstractrouter.hpp>
|
2019-06-15 14:55:13 +00:00
|
|
|
#include <routing/dht_message.hpp>
|
2019-09-01 13:26:16 +00:00
|
|
|
#include <util/thread/logic.hpp>
|
2019-03-27 12:36:27 +00:00
|
|
|
#include <nodedb.hpp>
|
2020-01-06 13:20:02 +00:00
|
|
|
#include <profiling.hpp>
|
2020-01-14 18:39:08 +00:00
|
|
|
#include <router/i_rc_lookup_handler.hpp>
|
2020-01-21 17:31:48 +00:00
|
|
|
#include <util/decaying_hashset.hpp>
|
2018-12-10 16:26:46 +00:00
|
|
|
#include <vector>
|
2018-07-11 13:20:14 +00:00
|
|
|
|
|
|
|
namespace llarp
|
|
|
|
{
|
|
|
|
namespace dht
|
|
|
|
{
|
2019-07-30 23:42:13 +00:00
|
|
|
AbstractContext::~AbstractContext() = default;
|
2019-01-24 01:31:02 +00:00
|
|
|
|
2019-02-22 15:08:00 +00:00
|
|
|
struct Context final : public AbstractContext
|
|
|
|
{
|
|
|
|
Context();
|
|
|
|
|
2019-07-30 23:42:13 +00:00
|
|
|
~Context() override = default;
|
2019-02-22 15:08:00 +00:00
|
|
|
|
|
|
|
util::StatusObject
|
|
|
|
ExtractStatus() const override;
|
|
|
|
|
2019-07-19 17:21:20 +00:00
|
|
|
void
|
|
|
|
StoreRC(const RouterContact rc) const override
|
|
|
|
{
|
2020-01-14 18:39:08 +00:00
|
|
|
GetRouter()->rcLookupHandler().CheckRC(rc);
|
2019-07-19 17:21:20 +00:00
|
|
|
}
|
|
|
|
|
2019-02-22 15:08:00 +00:00
|
|
|
void
|
2020-02-20 18:18:05 +00:00
|
|
|
LookupIntroSetRelayed(
|
2020-01-27 21:30:41 +00:00
|
|
|
const Key_t& target, const Key_t& whoasked, uint64_t whoaskedTX,
|
2020-02-20 18:18:05 +00:00
|
|
|
const Key_t& askpeer, uint64_t relayOrder,
|
2020-01-27 21:30:41 +00:00
|
|
|
service::EncryptedIntroSetLookupHandler result = nullptr) override;
|
2019-02-22 15:08:00 +00:00
|
|
|
|
|
|
|
void
|
2020-02-20 18:18:05 +00:00
|
|
|
LookupIntroSetDirect(
|
2020-01-27 21:30:41 +00:00
|
|
|
const Key_t& target, const Key_t& whoasked, uint64_t whoaskedTX,
|
|
|
|
const Key_t& askpeer,
|
|
|
|
service::EncryptedIntroSetLookupHandler result = nullptr) override;
|
2019-02-22 15:08:00 +00:00
|
|
|
|
|
|
|
/// on behalf of whoasked request router with public key target from dht
|
|
|
|
/// router with key askpeer
|
|
|
|
void
|
|
|
|
LookupRouterRecursive(const RouterID& target, const Key_t& whoasked,
|
|
|
|
uint64_t whoaskedTX, const Key_t& askpeer,
|
2019-04-19 15:10:26 +00:00
|
|
|
RouterLookupHandler result = nullptr) override;
|
2019-02-22 15:08:00 +00:00
|
|
|
|
|
|
|
bool
|
|
|
|
LookupRouter(const RouterID& target, RouterLookupHandler result) override
|
|
|
|
{
|
|
|
|
Key_t askpeer;
|
2019-04-25 23:21:19 +00:00
|
|
|
if(!_nodes->FindClosest(Key_t(target), askpeer))
|
2019-02-22 15:08:00 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
LookupRouterRecursive(target, OurKey(), 0, askpeer, result);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
HasRouterLookup(const RouterID& target) const override
|
|
|
|
{
|
|
|
|
return pendingRouterLookups().HasLookupFor(target);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// issue dht lookup for router via askpeer and send reply to local path
|
|
|
|
void
|
|
|
|
LookupRouterForPath(const RouterID& target, uint64_t txid,
|
|
|
|
const PathID_t& path, const Key_t& askpeer) override;
|
|
|
|
|
|
|
|
/// issue dht lookup for introset for addr via askpeer and send reply to
|
|
|
|
/// local path
|
|
|
|
void
|
2020-01-27 21:30:41 +00:00
|
|
|
LookupIntroSetForPath(const Key_t& addr, uint64_t txid,
|
2020-01-22 22:08:05 +00:00
|
|
|
const llarp::PathID_t& path, const Key_t& askpeer,
|
2020-02-14 18:06:19 +00:00
|
|
|
uint64_t relayOrder) override;
|
2019-02-22 15:08:00 +00:00
|
|
|
|
|
|
|
/// send a dht message to peer, if keepalive is true then keep the session
|
|
|
|
/// with that peer alive for 10 seconds
|
|
|
|
void
|
|
|
|
DHTSendTo(const RouterID& peer, IMessage* msg,
|
|
|
|
bool keepalive = true) override;
|
|
|
|
|
|
|
|
/// get routers closest to target excluding requester
|
|
|
|
bool
|
|
|
|
HandleExploritoryRouterLookup(
|
|
|
|
const Key_t& requester, uint64_t txid, const RouterID& target,
|
|
|
|
std::vector< std::unique_ptr< IMessage > >& reply) override;
|
|
|
|
|
|
|
|
/// handle rc lookup from requester for target
|
|
|
|
void
|
|
|
|
LookupRouterRelayed(
|
|
|
|
const Key_t& requester, uint64_t txid, const Key_t& target,
|
|
|
|
bool recursive,
|
|
|
|
std::vector< std::unique_ptr< IMessage > >& replies) override;
|
|
|
|
|
|
|
|
/// relay a dht message from a local path to the main network
|
|
|
|
bool
|
|
|
|
RelayRequestForPath(const llarp::PathID_t& localPath,
|
2019-04-22 17:38:29 +00:00
|
|
|
const IMessage& msg) override;
|
2019-02-22 15:08:00 +00:00
|
|
|
|
2020-03-01 17:30:05 +00:00
|
|
|
/// send introset to peer as R/S
|
|
|
|
void
|
|
|
|
PropagateLocalIntroSet(const PathID_t& from, uint64_t txid,
|
|
|
|
const service::EncryptedIntroSet& introset,
|
|
|
|
const Key_t& tellpeer, uint64_t relayOrder);
|
|
|
|
|
2019-02-22 15:08:00 +00:00
|
|
|
/// send introset to peer from source with S counter and excluding peers
|
|
|
|
void
|
2020-02-20 00:07:46 +00:00
|
|
|
PropagateIntroSetTo(const Key_t& from, uint64_t txid,
|
2020-01-27 21:30:41 +00:00
|
|
|
const service::EncryptedIntroSet& introset,
|
2020-03-01 17:30:05 +00:00
|
|
|
const Key_t& tellpeer, uint64_t relayOrder);
|
2019-02-22 15:08:00 +00:00
|
|
|
|
|
|
|
/// initialize dht context and explore every exploreInterval milliseconds
|
|
|
|
void
|
2020-02-27 16:37:23 +00:00
|
|
|
Init(const Key_t& us, AbstractRouter* router) override;
|
2019-02-22 15:08:00 +00:00
|
|
|
|
|
|
|
/// get localally stored introset by service address
|
2020-02-19 21:58:01 +00:00
|
|
|
nonstd::optional< llarp::service::EncryptedIntroSet >
|
2020-01-27 21:30:41 +00:00
|
|
|
GetIntroSetByLocation(const Key_t& location) const override;
|
2019-02-22 15:08:00 +00:00
|
|
|
|
2019-12-18 18:35:18 +00:00
|
|
|
void
|
|
|
|
handle_cleaner_timer(uint64_t interval);
|
2019-02-22 15:08:00 +00:00
|
|
|
|
|
|
|
/// explore dht for new routers
|
|
|
|
void
|
|
|
|
Explore(size_t N = 3);
|
|
|
|
|
2019-07-30 23:42:13 +00:00
|
|
|
llarp::AbstractRouter* router{nullptr};
|
2019-02-22 15:08:00 +00:00
|
|
|
// for router contacts
|
2019-04-25 23:21:19 +00:00
|
|
|
std::unique_ptr< Bucket< RCNode > > _nodes;
|
2019-02-22 15:08:00 +00:00
|
|
|
|
|
|
|
// for introduction sets
|
|
|
|
std::unique_ptr< Bucket< ISNode > > _services;
|
|
|
|
|
|
|
|
Bucket< ISNode >*
|
|
|
|
services() override
|
|
|
|
{
|
|
|
|
return _services.get();
|
|
|
|
}
|
|
|
|
|
2019-07-30 23:42:13 +00:00
|
|
|
bool allowTransit{false};
|
2019-02-22 15:08:00 +00:00
|
|
|
|
|
|
|
bool&
|
|
|
|
AllowTransit() override
|
|
|
|
{
|
|
|
|
return allowTransit;
|
|
|
|
}
|
|
|
|
const bool&
|
|
|
|
AllowTransit() const override
|
|
|
|
{
|
|
|
|
return allowTransit;
|
|
|
|
}
|
|
|
|
|
|
|
|
Bucket< RCNode >*
|
|
|
|
Nodes() const override
|
|
|
|
{
|
2019-04-25 23:21:19 +00:00
|
|
|
return _nodes.get();
|
2019-02-22 15:08:00 +00:00
|
|
|
}
|
|
|
|
|
2019-06-26 21:39:29 +00:00
|
|
|
void
|
|
|
|
PutRCNodeAsync(const RCNode& val) override
|
|
|
|
{
|
|
|
|
auto func = std::bind(&Bucket< RCNode >::PutNode, Nodes(), val);
|
2019-11-14 21:56:01 +00:00
|
|
|
LogicCall(router->logic(), func);
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
DelRCNodeAsync(const Key_t& val) override
|
|
|
|
{
|
|
|
|
auto func = std::bind(&Bucket< RCNode >::DelNode, Nodes(), val);
|
2019-11-14 21:56:01 +00:00
|
|
|
LogicCall(router->logic(), func);
|
2019-06-26 21:39:29 +00:00
|
|
|
}
|
|
|
|
|
2019-02-22 15:08:00 +00:00
|
|
|
const Key_t&
|
|
|
|
OurKey() const override
|
|
|
|
{
|
|
|
|
return ourKey;
|
|
|
|
}
|
|
|
|
|
|
|
|
llarp::AbstractRouter*
|
|
|
|
GetRouter() const override
|
|
|
|
{
|
|
|
|
return router;
|
|
|
|
}
|
|
|
|
|
2019-03-27 12:36:27 +00:00
|
|
|
bool
|
|
|
|
GetRCFromNodeDB(const Key_t& k, llarp::RouterContact& rc) const override
|
|
|
|
{
|
|
|
|
return router->nodedb()->Get(k.as_array(), rc);
|
|
|
|
}
|
|
|
|
|
2019-02-22 15:08:00 +00:00
|
|
|
PendingIntrosetLookups _pendingIntrosetLookups;
|
|
|
|
PendingRouterLookups _pendingRouterLookups;
|
|
|
|
PendingExploreLookups _pendingExploreLookups;
|
|
|
|
|
|
|
|
PendingIntrosetLookups&
|
|
|
|
pendingIntrosetLookups() override
|
|
|
|
{
|
|
|
|
return _pendingIntrosetLookups;
|
|
|
|
}
|
|
|
|
|
|
|
|
const PendingIntrosetLookups&
|
|
|
|
pendingIntrosetLookups() const override
|
|
|
|
{
|
|
|
|
return _pendingIntrosetLookups;
|
|
|
|
}
|
|
|
|
|
|
|
|
PendingRouterLookups&
|
|
|
|
pendingRouterLookups() override
|
|
|
|
{
|
|
|
|
return _pendingRouterLookups;
|
|
|
|
}
|
|
|
|
|
|
|
|
const PendingRouterLookups&
|
|
|
|
pendingRouterLookups() const override
|
|
|
|
{
|
|
|
|
return _pendingRouterLookups;
|
|
|
|
}
|
|
|
|
|
|
|
|
PendingExploreLookups&
|
|
|
|
pendingExploreLookups() override
|
|
|
|
{
|
|
|
|
return _pendingExploreLookups;
|
|
|
|
}
|
|
|
|
|
|
|
|
const PendingExploreLookups&
|
|
|
|
pendingExploreLookups() const override
|
|
|
|
{
|
|
|
|
return _pendingExploreLookups;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
NextID()
|
|
|
|
{
|
|
|
|
return ++ids;
|
|
|
|
}
|
|
|
|
|
|
|
|
llarp_time_t
|
|
|
|
Now() const override;
|
|
|
|
|
|
|
|
void
|
|
|
|
ExploreNetworkVia(const Key_t& peer) override;
|
|
|
|
|
|
|
|
private:
|
|
|
|
void
|
|
|
|
ScheduleCleanupTimer();
|
|
|
|
|
|
|
|
void
|
|
|
|
CleanupTX();
|
|
|
|
|
|
|
|
uint64_t ids;
|
|
|
|
|
|
|
|
Key_t ourKey;
|
|
|
|
};
|
|
|
|
|
2020-02-29 22:43:51 +00:00
|
|
|
Context::Context()
|
2018-07-11 13:20:14 +00:00
|
|
|
{
|
2019-02-22 15:08:00 +00:00
|
|
|
randombytes((byte_t*)&ids, sizeof(uint64_t));
|
2018-07-11 13:20:14 +00:00
|
|
|
}
|
|
|
|
|
2018-08-27 13:44:16 +00:00
|
|
|
void
|
2018-09-06 20:31:58 +00:00
|
|
|
Context::Explore(size_t N)
|
2018-08-27 13:44:16 +00:00
|
|
|
{
|
2018-08-29 20:40:26 +00:00
|
|
|
// ask N random peers for new routers
|
2019-07-17 12:25:51 +00:00
|
|
|
llarp::LogDebug("Exploring network via ", N, " peers");
|
2018-08-29 20:40:26 +00:00
|
|
|
std::set< Key_t > peers;
|
|
|
|
|
2019-04-25 23:21:19 +00:00
|
|
|
if(_nodes->GetManyRandom(peers, N))
|
2018-08-27 13:44:16 +00:00
|
|
|
{
|
2019-02-22 15:08:00 +00:00
|
|
|
for(const auto& peer : peers)
|
2018-08-29 20:40:26 +00:00
|
|
|
ExploreNetworkVia(peer);
|
2018-08-27 13:44:16 +00:00
|
|
|
}
|
2018-08-29 20:40:26 +00:00
|
|
|
else
|
2019-07-17 12:25:51 +00:00
|
|
|
llarp::LogError("failed to select ", N,
|
|
|
|
" random nodes for exploration");
|
2018-08-27 13:44:16 +00:00
|
|
|
}
|
|
|
|
|
2018-08-29 20:40:26 +00:00
|
|
|
void
|
2019-02-22 15:08:00 +00:00
|
|
|
Context::ExploreNetworkVia(const Key_t& askpeer)
|
2018-08-29 20:40:26 +00:00
|
|
|
{
|
2018-11-28 15:27:36 +00:00
|
|
|
uint64_t txid = ++ids;
|
2019-07-30 15:59:12 +00:00
|
|
|
const TXOwner peer(askpeer, txid);
|
|
|
|
const TXOwner whoasked(OurKey(), txid);
|
|
|
|
const RouterID K(askpeer.as_array());
|
2019-02-22 15:08:00 +00:00
|
|
|
pendingExploreLookups().NewTX(
|
2019-07-29 13:08:40 +00:00
|
|
|
peer, whoasked, K, new ExploreNetworkJob(askpeer.as_array(), this));
|
2018-08-27 13:44:16 +00:00
|
|
|
}
|
|
|
|
|
2018-07-11 13:20:14 +00:00
|
|
|
void
|
2019-12-18 18:35:18 +00:00
|
|
|
Context::handle_cleaner_timer(__attribute__((unused)) uint64_t interval)
|
2018-07-11 13:20:14 +00:00
|
|
|
{
|
2018-08-27 13:44:16 +00:00
|
|
|
// clean up transactions
|
2019-12-18 18:35:18 +00:00
|
|
|
CleanupTX();
|
2020-01-21 17:31:48 +00:00
|
|
|
const llarp_time_t now = Now();
|
2018-08-27 13:44:16 +00:00
|
|
|
|
2019-12-18 18:35:18 +00:00
|
|
|
if(_services)
|
2018-07-18 00:25:24 +00:00
|
|
|
{
|
|
|
|
// expire intro sets
|
2019-12-18 18:35:18 +00:00
|
|
|
auto& nodes = _services->nodes;
|
2018-07-18 00:25:24 +00:00
|
|
|
auto itr = nodes.begin();
|
|
|
|
while(itr != nodes.end())
|
|
|
|
{
|
|
|
|
if(itr->second.introset.IsExpired(now))
|
2018-08-04 02:59:32 +00:00
|
|
|
{
|
2018-07-18 00:25:24 +00:00
|
|
|
itr = nodes.erase(itr);
|
2018-08-04 02:59:32 +00:00
|
|
|
}
|
2018-07-18 00:25:24 +00:00
|
|
|
else
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
}
|
2019-12-18 18:35:18 +00:00
|
|
|
ScheduleCleanupTimer();
|
2018-07-11 13:20:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-09-02 18:25:42 +00:00
|
|
|
Context::LookupRouterRelayed(
|
2019-02-22 15:08:00 +00:00
|
|
|
const Key_t& requester, uint64_t txid, const Key_t& target,
|
|
|
|
bool recursive, std::vector< std::unique_ptr< IMessage > >& replies)
|
2018-07-11 13:20:14 +00:00
|
|
|
{
|
|
|
|
if(target == ourKey)
|
|
|
|
{
|
|
|
|
// we are the target, give them our RC
|
2018-09-02 18:25:42 +00:00
|
|
|
replies.emplace_back(
|
2018-09-09 11:23:21 +00:00
|
|
|
new GotRouterMessage(requester, txid, {router->rc()}, false));
|
2018-07-11 13:20:14 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-01-23 12:11:11 +00:00
|
|
|
if(not GetRouter()->ConnectionToRouterAllowed(target.as_array()))
|
|
|
|
{
|
|
|
|
// explicitly not allowed
|
|
|
|
replies.emplace_back(new GotRouterMessage(requester, txid, {}, false));
|
|
|
|
return;
|
|
|
|
}
|
2020-01-22 22:33:39 +00:00
|
|
|
const auto rc = GetRouter()->nodedb()->FindClosestTo(target);
|
2020-01-23 12:11:11 +00:00
|
|
|
const Key_t next(rc.pubkey);
|
2018-07-11 13:20:14 +00:00
|
|
|
{
|
|
|
|
if(next == target)
|
|
|
|
{
|
2020-01-23 12:11:11 +00:00
|
|
|
// we know the target
|
|
|
|
if(rc.ExpiresSoon(llarp::time_now_ms()))
|
|
|
|
{
|
|
|
|
// ask target for their rc to keep it updated
|
|
|
|
LookupRouterRecursive(target.as_array(), requester, txid, next);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// send reply with rc we know of
|
|
|
|
replies.emplace_back(
|
|
|
|
new GotRouterMessage(requester, txid, {rc}, false));
|
|
|
|
}
|
2018-07-11 13:20:14 +00:00
|
|
|
}
|
|
|
|
else if(recursive) // are we doing a recursive lookup?
|
|
|
|
{
|
2018-08-29 20:40:26 +00:00
|
|
|
// is the next peer we ask closer to the target than us?
|
|
|
|
if((next ^ target) < (ourKey ^ target))
|
2018-07-11 13:20:14 +00:00
|
|
|
{
|
2019-01-02 01:03:53 +00:00
|
|
|
// yes it is closer, ask neighbour recursively
|
|
|
|
LookupRouterRecursive(target.as_array(), requester, txid, next);
|
2018-07-11 13:20:14 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-08-29 20:40:26 +00:00
|
|
|
// no we are closer to the target so tell requester it's not there
|
|
|
|
// so they switch to iterative lookup
|
2018-09-02 18:25:42 +00:00
|
|
|
replies.emplace_back(
|
|
|
|
new GotRouterMessage(requester, txid, {}, false));
|
2018-07-11 13:20:14 +00:00
|
|
|
}
|
|
|
|
}
|
2018-11-08 15:15:02 +00:00
|
|
|
else
|
2018-07-11 13:20:14 +00:00
|
|
|
{
|
2018-11-08 15:15:02 +00:00
|
|
|
// iterative lookup and we don't have it tell them who is closer
|
2018-09-02 18:25:42 +00:00
|
|
|
replies.emplace_back(
|
2018-11-08 15:15:02 +00:00
|
|
|
new GotRouterMessage(requester, next, txid, false));
|
2018-07-11 13:20:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-19 21:58:01 +00:00
|
|
|
nonstd::optional< llarp::service::EncryptedIntroSet >
|
2020-01-27 21:30:41 +00:00
|
|
|
Context::GetIntroSetByLocation(const Key_t& key) const
|
2018-07-16 21:22:25 +00:00
|
|
|
{
|
2019-02-22 15:08:00 +00:00
|
|
|
auto itr = _services->nodes.find(key);
|
|
|
|
if(itr == _services->nodes.end())
|
2020-01-27 21:30:41 +00:00
|
|
|
return {};
|
|
|
|
return itr->second.introset;
|
2018-07-16 21:22:25 +00:00
|
|
|
}
|
|
|
|
|
2018-07-11 13:20:14 +00:00
|
|
|
void
|
|
|
|
Context::CleanupTX()
|
|
|
|
{
|
2018-10-29 16:48:36 +00:00
|
|
|
auto now = Now();
|
2018-07-11 13:20:14 +00:00
|
|
|
llarp::LogDebug("DHT tick");
|
|
|
|
|
2019-02-22 15:08:00 +00:00
|
|
|
pendingRouterLookups().Expire(now);
|
|
|
|
_pendingIntrosetLookups.Expire(now);
|
|
|
|
pendingExploreLookups().Expire(now);
|
2018-07-11 13:20:14 +00:00
|
|
|
}
|
|
|
|
|
2019-02-11 17:14:43 +00:00
|
|
|
util::StatusObject
|
|
|
|
Context::ExtractStatus() const
|
2019-02-08 19:43:25 +00:00
|
|
|
{
|
2019-02-11 17:14:43 +00:00
|
|
|
util::StatusObject obj{
|
2019-02-22 15:08:00 +00:00
|
|
|
{"pendingRouterLookups", pendingRouterLookups().ExtractStatus()},
|
|
|
|
{"pendingIntrosetLookups", _pendingIntrosetLookups.ExtractStatus()},
|
|
|
|
{"pendingExploreLookups", pendingExploreLookups().ExtractStatus()},
|
2019-04-25 23:21:19 +00:00
|
|
|
{"nodes", _nodes->ExtractStatus()},
|
2019-02-22 15:08:00 +00:00
|
|
|
{"services", _services->ExtractStatus()},
|
2019-02-11 17:14:43 +00:00
|
|
|
{"ourKey", ourKey.ToHex()}};
|
|
|
|
return obj;
|
2019-02-08 19:43:25 +00:00
|
|
|
}
|
|
|
|
|
2018-07-11 13:20:14 +00:00
|
|
|
void
|
2020-02-27 16:37:23 +00:00
|
|
|
Context::Init(const Key_t& us, AbstractRouter* r)
|
2018-07-11 13:20:14 +00:00
|
|
|
{
|
2020-02-14 18:59:54 +00:00
|
|
|
router = r;
|
2019-02-22 15:08:00 +00:00
|
|
|
ourKey = us;
|
2019-04-25 23:21:19 +00:00
|
|
|
_nodes = std::make_unique< Bucket< RCNode > >(ourKey, llarp::randint);
|
2019-02-22 15:08:00 +00:00
|
|
|
_services = std::make_unique< Bucket< ISNode > >(ourKey, llarp::randint);
|
2019-01-16 00:24:16 +00:00
|
|
|
llarp::LogDebug("initialize dht with key ", ourKey);
|
2018-10-27 20:02:24 +00:00
|
|
|
// start cleanup timer
|
|
|
|
ScheduleCleanupTimer();
|
2018-07-11 13:20:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Context::ScheduleCleanupTimer()
|
|
|
|
{
|
2019-12-22 14:16:28 +00:00
|
|
|
router->logic()->call_later(
|
2020-02-24 19:40:45 +00:00
|
|
|
1s,
|
2019-12-22 14:16:28 +00:00
|
|
|
std::bind(&llarp::dht::Context::handle_cleaner_timer, this, 1000));
|
2018-07-11 13:20:14 +00:00
|
|
|
}
|
|
|
|
|
2018-08-10 21:34:11 +00:00
|
|
|
void
|
2019-05-06 14:21:47 +00:00
|
|
|
Context::DHTSendTo(const RouterID& peer, IMessage* msg, bool)
|
2018-08-10 21:34:11 +00:00
|
|
|
{
|
2019-01-19 13:54:50 +00:00
|
|
|
llarp::DHTImmediateMessage m;
|
2018-09-02 18:25:42 +00:00
|
|
|
m.msgs.emplace_back(msg);
|
2020-02-28 23:56:35 +00:00
|
|
|
router->SendToOrQueue(peer, &m, [](SendStatus status) {
|
2020-02-29 00:07:35 +00:00
|
|
|
if(status != SendStatus::Success)
|
2020-02-28 23:56:35 +00:00
|
|
|
LogInfo("DHTSendTo unsuccessful, status: ", (int)status);
|
|
|
|
});
|
2019-05-06 14:21:47 +00:00
|
|
|
auto now = Now();
|
2020-02-24 19:40:45 +00:00
|
|
|
router->PersistSessionUntil(peer, now + 1min);
|
2018-08-10 21:34:11 +00:00
|
|
|
}
|
|
|
|
|
2020-02-28 16:46:50 +00:00
|
|
|
// this function handles incoming DHT messages sent down a path by a client
|
|
|
|
// note that IMessage here is different than that found in the routing
|
|
|
|
// namespace. by the time this is called, we are inside
|
|
|
|
// llarp::routing::DHTMessage::HandleMessage()
|
2018-07-11 13:20:14 +00:00
|
|
|
bool
|
2019-04-22 17:38:29 +00:00
|
|
|
Context::RelayRequestForPath(const llarp::PathID_t& id, const IMessage& msg)
|
2018-07-11 13:20:14 +00:00
|
|
|
{
|
|
|
|
llarp::routing::DHTMessage reply;
|
2019-04-22 17:38:29 +00:00
|
|
|
if(!msg.HandleMessage(router->dht(), reply.M))
|
2018-07-11 13:20:14 +00:00
|
|
|
return false;
|
2020-01-21 17:31:48 +00:00
|
|
|
if(not reply.M.empty())
|
2018-08-10 03:51:38 +00:00
|
|
|
{
|
2019-01-29 02:16:31 +00:00
|
|
|
auto path = router->pathContext().GetByUpstream(router->pubkey(), id);
|
2019-04-22 17:38:29 +00:00
|
|
|
return path && path->SendRoutingMessage(reply, router);
|
2018-08-10 03:51:38 +00:00
|
|
|
}
|
|
|
|
return true;
|
2018-07-11 13:20:14 +00:00
|
|
|
}
|
|
|
|
|
2018-08-29 20:40:26 +00:00
|
|
|
void
|
2020-01-27 21:30:41 +00:00
|
|
|
Context::LookupIntroSetForPath(const Key_t& addr, uint64_t txid,
|
2019-02-22 15:08:00 +00:00
|
|
|
const llarp::PathID_t& path,
|
2020-02-20 20:14:20 +00:00
|
|
|
const Key_t& askpeer, uint64_t relayOrder)
|
2018-08-29 20:40:26 +00:00
|
|
|
{
|
2020-03-01 15:59:19 +00:00
|
|
|
const TXOwner asker(OurKey(), txid);
|
|
|
|
const TXOwner peer(askpeer, ++ids);
|
2019-02-22 15:08:00 +00:00
|
|
|
_pendingIntrosetLookups.NewTX(
|
2020-03-01 15:59:19 +00:00
|
|
|
peer, asker, asker,
|
2020-02-13 22:19:12 +00:00
|
|
|
new LocalServiceAddressLookup(path, txid, relayOrder, addr, this,
|
2020-02-20 18:18:05 +00:00
|
|
|
askpeer));
|
2018-08-29 20:40:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-02-22 15:08:00 +00:00
|
|
|
Context::PropagateIntroSetTo(const Key_t& from, uint64_t txid,
|
2020-01-27 21:30:41 +00:00
|
|
|
const service::EncryptedIntroSet& introset,
|
2020-03-01 17:30:05 +00:00
|
|
|
const Key_t& tellpeer, uint64_t relayOrder)
|
2018-08-29 20:40:26 +00:00
|
|
|
{
|
2020-03-01 15:59:19 +00:00
|
|
|
const TXOwner asker(from, txid);
|
|
|
|
const TXOwner peer(tellpeer, ++ids);
|
2019-02-22 15:08:00 +00:00
|
|
|
_pendingIntrosetLookups.NewTX(
|
2020-03-01 15:59:19 +00:00
|
|
|
peer, asker, asker,
|
2020-03-01 17:30:05 +00:00
|
|
|
new PublishServiceJob(asker, introset, this, relayOrder));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Context::PropagateLocalIntroSet(const PathID_t& from, uint64_t txid,
|
|
|
|
const service::EncryptedIntroSet& introset,
|
|
|
|
const Key_t& tellpeer, uint64_t relayOrder)
|
2018-08-29 20:40:26 +00:00
|
|
|
{
|
2020-03-01 17:30:05 +00:00
|
|
|
const TXOwner asker(OurKey(), txid);
|
|
|
|
const TXOwner peer(tellpeer, ++ids);
|
2019-02-22 15:08:00 +00:00
|
|
|
_pendingIntrosetLookups.NewTX(
|
2020-03-01 17:30:05 +00:00
|
|
|
peer, asker, peer,
|
|
|
|
new LocalPublishServiceJob(peer, from, txid, introset, this,
|
|
|
|
relayOrder));
|
2018-08-29 20:40:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-20 18:18:05 +00:00
|
|
|
Context::LookupIntroSetRelayed(
|
2020-01-27 21:30:41 +00:00
|
|
|
const Key_t& addr, const Key_t& whoasked, uint64_t txid,
|
2020-02-20 18:18:05 +00:00
|
|
|
const Key_t& askpeer, uint64_t relayOrder,
|
2020-01-27 21:30:41 +00:00
|
|
|
service::EncryptedIntroSetLookupHandler handler)
|
2018-08-29 20:40:26 +00:00
|
|
|
{
|
2020-03-01 15:59:19 +00:00
|
|
|
const TXOwner asker(whoasked, txid);
|
|
|
|
const TXOwner peer(askpeer, ++ids);
|
2019-02-22 15:08:00 +00:00
|
|
|
_pendingIntrosetLookups.NewTX(
|
2020-03-01 15:59:19 +00:00
|
|
|
peer, asker, asker,
|
2020-02-20 18:18:05 +00:00
|
|
|
new ServiceAddressLookup(asker, addr, this, relayOrder, handler));
|
2018-08-29 20:40:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-20 18:18:05 +00:00
|
|
|
Context::LookupIntroSetDirect(
|
2020-01-27 21:30:41 +00:00
|
|
|
const Key_t& addr, const Key_t& whoasked, uint64_t txid,
|
|
|
|
const Key_t& askpeer, service::EncryptedIntroSetLookupHandler handler)
|
2018-08-29 20:40:26 +00:00
|
|
|
{
|
2020-03-01 15:59:19 +00:00
|
|
|
const TXOwner asker(whoasked, txid);
|
|
|
|
const TXOwner peer(askpeer, ++ids);
|
2019-02-22 15:08:00 +00:00
|
|
|
_pendingIntrosetLookups.NewTX(
|
2020-03-01 15:59:19 +00:00
|
|
|
peer, asker, asker,
|
2020-02-24 19:40:45 +00:00
|
|
|
new ServiceAddressLookup(asker, addr, this, 0, handler), 1s);
|
2018-08-29 20:40:26 +00:00
|
|
|
}
|
|
|
|
|
2018-08-27 13:44:16 +00:00
|
|
|
bool
|
2018-09-02 18:25:42 +00:00
|
|
|
Context::HandleExploritoryRouterLookup(
|
2019-02-22 15:08:00 +00:00
|
|
|
const Key_t& requester, uint64_t txid, const RouterID& target,
|
|
|
|
std::vector< std::unique_ptr< IMessage > >& reply)
|
2018-08-27 13:44:16 +00:00
|
|
|
{
|
|
|
|
std::vector< RouterID > closer;
|
2019-05-09 12:48:21 +00:00
|
|
|
const Key_t t(target.as_array());
|
2019-07-30 15:59:12 +00:00
|
|
|
std::set< Key_t > foundRouters;
|
2019-04-25 23:21:19 +00:00
|
|
|
if(!_nodes)
|
2018-11-19 17:14:35 +00:00
|
|
|
return false;
|
2018-12-18 18:36:19 +00:00
|
|
|
|
2019-05-09 12:48:21 +00:00
|
|
|
const size_t nodeCount = _nodes->size();
|
2018-09-09 12:27:56 +00:00
|
|
|
if(nodeCount == 0)
|
|
|
|
{
|
|
|
|
llarp::LogError(
|
|
|
|
"cannot handle exploritory router lookup, no dht peers");
|
|
|
|
return false;
|
|
|
|
}
|
2019-04-25 23:21:19 +00:00
|
|
|
llarp::LogDebug("We have ", _nodes->size(),
|
2018-12-23 13:29:11 +00:00
|
|
|
" connected nodes into the DHT");
|
2018-12-18 18:53:11 +00:00
|
|
|
// ourKey should never be in the connected list
|
|
|
|
// requester is likely in the connected list
|
|
|
|
// 4 or connection nodes (minus a potential requestor), whatever is less
|
2019-07-30 15:59:12 +00:00
|
|
|
if(!_nodes->GetManyNearExcluding(t, foundRouters,
|
2019-07-30 17:57:23 +00:00
|
|
|
std::min(nodeCount, size_t{4}),
|
2019-04-25 23:21:19 +00:00
|
|
|
std::set< Key_t >{ourKey, requester}))
|
2018-08-27 13:44:16 +00:00
|
|
|
{
|
|
|
|
llarp::LogError(
|
2018-09-09 12:27:56 +00:00
|
|
|
"not enough dht nodes to handle exploritory router lookup, "
|
2019-05-20 12:19:33 +00:00
|
|
|
"have ",
|
|
|
|
nodeCount, " dht peers");
|
2018-08-27 13:44:16 +00:00
|
|
|
return false;
|
|
|
|
}
|
2019-07-30 15:59:12 +00:00
|
|
|
for(const auto& f : foundRouters)
|
2019-05-09 12:48:21 +00:00
|
|
|
{
|
2020-02-13 15:51:25 +00:00
|
|
|
const RouterID id = f.as_array();
|
2020-01-06 13:16:20 +00:00
|
|
|
// discard shit routers
|
2020-02-13 15:51:25 +00:00
|
|
|
if(router->routerProfiling().IsBadForConnect(id))
|
2020-01-06 13:16:20 +00:00
|
|
|
continue;
|
2020-02-13 15:51:25 +00:00
|
|
|
closer.emplace_back(id);
|
2019-05-09 12:48:21 +00:00
|
|
|
}
|
2019-07-30 15:59:12 +00:00
|
|
|
llarp::LogDebug("Gave ", closer.size(), " routers for exploration");
|
2018-09-02 18:25:42 +00:00
|
|
|
reply.emplace_back(new GotRouterMessage(txid, closer, false));
|
2018-08-27 13:44:16 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-08-31 12:46:54 +00:00
|
|
|
void
|
2019-02-22 15:08:00 +00:00
|
|
|
Context::LookupRouterForPath(const RouterID& target, uint64_t txid,
|
|
|
|
const llarp::PathID_t& path,
|
|
|
|
const Key_t& askpeer)
|
2018-08-31 12:46:54 +00:00
|
|
|
|
|
|
|
{
|
2019-07-19 17:21:20 +00:00
|
|
|
const TXOwner peer(askpeer, ++ids);
|
|
|
|
const TXOwner whoasked(OurKey(), txid);
|
2019-02-22 15:08:00 +00:00
|
|
|
_pendingRouterLookups.NewTX(
|
2018-11-08 15:15:02 +00:00
|
|
|
peer, whoasked, target,
|
|
|
|
new LocalRouterLookup(path, txid, target, this));
|
2018-08-31 12:46:54 +00:00
|
|
|
}
|
|
|
|
|
2018-08-29 20:40:26 +00:00
|
|
|
void
|
2019-02-22 15:08:00 +00:00
|
|
|
Context::LookupRouterRecursive(const RouterID& target,
|
|
|
|
const Key_t& whoasked, uint64_t txid,
|
|
|
|
const Key_t& askpeer,
|
2018-08-30 18:48:43 +00:00
|
|
|
RouterLookupHandler handler)
|
2018-08-29 20:40:26 +00:00
|
|
|
{
|
2019-07-19 17:21:20 +00:00
|
|
|
const TXOwner asker(whoasked, txid);
|
|
|
|
const TXOwner peer(askpeer, ++ids);
|
2019-07-17 12:25:51 +00:00
|
|
|
_pendingRouterLookups.NewTX(
|
|
|
|
peer, asker, target,
|
|
|
|
new RecursiveRouterLookup(asker, target, this, handler));
|
2018-07-11 13:20:14 +00:00
|
|
|
}
|
|
|
|
|
2018-10-29 16:48:36 +00:00
|
|
|
llarp_time_t
|
2019-01-24 01:31:02 +00:00
|
|
|
Context::Now() const
|
2018-10-29 16:48:36 +00:00
|
|
|
{
|
2019-01-29 02:16:31 +00:00
|
|
|
return router->Now();
|
2018-10-29 16:48:36 +00:00
|
|
|
}
|
|
|
|
|
2019-02-22 19:04:47 +00:00
|
|
|
std::unique_ptr< AbstractContext >
|
|
|
|
makeContext()
|
|
|
|
{
|
|
|
|
return std::make_unique< Context >();
|
|
|
|
}
|
|
|
|
|
2018-07-11 13:20:14 +00:00
|
|
|
} // namespace dht
|
2018-07-13 09:27:57 +00:00
|
|
|
} // namespace llarp
|