mirror of https://github.com/oxen-io/lokinet
Compilation fixes
- almost all errors have been commented out for refactor or already refactored - committing this prior to sorting out the cmake structure - upcoming include-what-you-use applicationpull/2213/head
parent
3ae8fce77d
commit
0e451db77f
@ -1,38 +0,0 @@
|
||||
#include "explorenetworkjob.hpp"
|
||||
|
||||
#include <llarp/router/router.hpp>
|
||||
|
||||
#include <llarp/nodedb.hpp>
|
||||
|
||||
#include <llarp/tooling/dht_event.hpp>
|
||||
|
||||
namespace llarp::dht
|
||||
{
|
||||
void
|
||||
ExploreNetworkJob::Start(const TXOwner& peer)
|
||||
{
|
||||
auto msg = new FindRouterMessage(peer.txid);
|
||||
auto router = parent->GetRouter();
|
||||
if (router)
|
||||
{
|
||||
router->notify_router_event<tooling::FindRouterSentEvent>(router->pubkey(), *msg);
|
||||
}
|
||||
parent->DHTSendTo(peer.node.as_array(), msg);
|
||||
}
|
||||
|
||||
void
|
||||
ExploreNetworkJob::SendReply()
|
||||
{
|
||||
llarp::LogDebug("got ", valuesFound.size(), " routers from exploration");
|
||||
|
||||
auto router = parent->GetRouter();
|
||||
for (const auto& pk : valuesFound)
|
||||
{
|
||||
// lookup router
|
||||
if (router and router->node_db()->Has(pk))
|
||||
continue;
|
||||
parent->LookupRouter(
|
||||
pk, [router, pk](const auto& res) { router->HandleDHTLookupForExplore(pk, res); });
|
||||
}
|
||||
}
|
||||
} // namespace llarp::dht
|
@ -1,30 +0,0 @@
|
||||
#ifndef LLARP_DHT_EXPLORENETWORKJOB
|
||||
#define LLARP_DHT_EXPLORENETWORKJOB
|
||||
|
||||
#include "tx.hpp"
|
||||
#include <llarp/router_id.hpp>
|
||||
|
||||
namespace llarp::dht
|
||||
{
|
||||
struct ExploreNetworkJob : public TX<RouterID, RouterID>
|
||||
{
|
||||
ExploreNetworkJob(const RouterID& peer, AbstractDHTMessageHandler* ctx)
|
||||
: TX<RouterID, RouterID>(TXOwner{}, peer, ctx)
|
||||
{}
|
||||
|
||||
bool
|
||||
Validate(const RouterID&) const override
|
||||
{
|
||||
// TODO: check with lokid
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Start(const TXOwner& peer) override;
|
||||
|
||||
void
|
||||
SendReply() override;
|
||||
};
|
||||
} // namespace llarp::dht
|
||||
|
||||
#endif
|
@ -1,61 +0,0 @@
|
||||
#include "localrouterlookup.hpp"
|
||||
|
||||
#include "context.hpp"
|
||||
#include <llarp/dht/messages/gotrouter.hpp>
|
||||
|
||||
#include <llarp/path/path_context.hpp>
|
||||
#include <llarp/router/router.hpp>
|
||||
#include <llarp/routing/path_dht_message.hpp>
|
||||
#include <llarp/util/logging.hpp>
|
||||
|
||||
namespace llarp::dht
|
||||
{
|
||||
LocalRouterLookup::LocalRouterLookup(
|
||||
const PathID_t& path, uint64_t txid, const RouterID& _target, AbstractDHTMessageHandler* ctx)
|
||||
: RecursiveRouterLookup(TXOwner{ctx->OurKey(), txid}, _target, ctx, nullptr), localPath(path)
|
||||
{}
|
||||
|
||||
void
|
||||
LocalRouterLookup::SendReply()
|
||||
{
|
||||
auto path =
|
||||
parent->GetRouter()->path_context().GetByUpstream(parent->OurKey().as_array(), localPath);
|
||||
if (!path)
|
||||
{
|
||||
llarp::LogWarn(
|
||||
"did not send reply for relayed dht request, no such local path "
|
||||
"for pathid=",
|
||||
localPath);
|
||||
return;
|
||||
}
|
||||
if (valuesFound.size())
|
||||
{
|
||||
RouterContact found;
|
||||
for (const auto& rc : valuesFound)
|
||||
{
|
||||
if (rc.OtherIsNewer(found))
|
||||
found = rc;
|
||||
}
|
||||
valuesFound.clear();
|
||||
if (not found.pubkey.IsZero())
|
||||
{
|
||||
valuesFound.resize(1);
|
||||
valuesFound[0] = found;
|
||||
}
|
||||
else
|
||||
{
|
||||
llarp::LogWarn("We found a null RC for dht request, dropping it");
|
||||
}
|
||||
}
|
||||
routing::PathDHTMessage msg;
|
||||
msg.dht_msgs.emplace_back(
|
||||
new GotRouterMessage(parent->OurKey(), whoasked.txid, valuesFound, true));
|
||||
if (!path->SendRoutingMessage(msg, parent->GetRouter()))
|
||||
{
|
||||
llarp::LogWarn(
|
||||
"failed to send routing message when informing result of dht "
|
||||
"request, pathid=",
|
||||
localPath);
|
||||
}
|
||||
}
|
||||
} // namespace llarp::dht
|
@ -1,27 +0,0 @@
|
||||
#ifndef LLARP_DHT_LOCALROUTERLOOKUP
|
||||
#define LLARP_DHT_LOCALROUTERLOOKUP
|
||||
|
||||
#include "recursiverouterlookup.hpp"
|
||||
|
||||
#include <llarp/path/path_types.hpp>
|
||||
#include <llarp/router_contact.hpp>
|
||||
#include <llarp/router_id.hpp>
|
||||
|
||||
namespace llarp::dht
|
||||
{
|
||||
struct LocalRouterLookup : public RecursiveRouterLookup
|
||||
{
|
||||
PathID_t localPath;
|
||||
|
||||
LocalRouterLookup(
|
||||
const PathID_t& path,
|
||||
uint64_t txid,
|
||||
const RouterID& target,
|
||||
AbstractDHTMessageHandler* ctx);
|
||||
|
||||
void
|
||||
SendReply() override;
|
||||
};
|
||||
} // namespace llarp::dht
|
||||
|
||||
#endif
|
@ -1,58 +0,0 @@
|
||||
#include "localserviceaddresslookup.hpp"
|
||||
|
||||
#include "context.hpp"
|
||||
#include <llarp/dht/messages/gotintro.hpp>
|
||||
#include <llarp/path/path_context.hpp>
|
||||
#include <llarp/router/router.hpp>
|
||||
#include <llarp/routing/path_dht_message.hpp>
|
||||
#include <llarp/util/logging.hpp>
|
||||
|
||||
namespace llarp::dht
|
||||
{
|
||||
LocalServiceAddressLookup::LocalServiceAddressLookup(
|
||||
const PathID_t& pathid,
|
||||
uint64_t txid,
|
||||
uint64_t relayOrder,
|
||||
const Key_t& addr,
|
||||
AbstractDHTMessageHandler* ctx,
|
||||
[[maybe_unused]] const Key_t& askpeer)
|
||||
: ServiceAddressLookup(TXOwner{ctx->OurKey(), txid}, addr, ctx, relayOrder, nullptr)
|
||||
, localPath(pathid)
|
||||
{}
|
||||
|
||||
void
|
||||
LocalServiceAddressLookup::SendReply()
|
||||
{
|
||||
auto path =
|
||||
parent->GetRouter()->path_context().GetByUpstream(parent->OurKey().as_array(), localPath);
|
||||
if (!path)
|
||||
{
|
||||
llarp::LogWarn(
|
||||
"did not send reply for relayed dht request, no such local path "
|
||||
"for pathid=",
|
||||
localPath);
|
||||
return;
|
||||
}
|
||||
// pick newest if we have more than 1 result
|
||||
if (valuesFound.size())
|
||||
{
|
||||
service::EncryptedIntroSet found;
|
||||
for (const auto& introset : valuesFound)
|
||||
{
|
||||
if (found.OtherIsNewer(introset))
|
||||
found = introset;
|
||||
}
|
||||
valuesFound.clear();
|
||||
valuesFound.emplace_back(found);
|
||||
}
|
||||
routing::PathDHTMessage msg;
|
||||
msg.dht_msgs.emplace_back(new GotIntroMessage(valuesFound, whoasked.txid));
|
||||
if (!path->SendRoutingMessage(msg, parent->GetRouter()))
|
||||
{
|
||||
llarp::LogWarn(
|
||||
"failed to send routing message when informing result of dht "
|
||||
"request, pathid=",
|
||||
localPath);
|
||||
}
|
||||
}
|
||||
} // namespace llarp::dht
|
@ -1,28 +0,0 @@
|
||||
#ifndef LLARP_DHT_LOCALSERVICEADDRESSLOOKUP
|
||||
#define LLARP_DHT_LOCALSERVICEADDRESSLOOKUP
|
||||
|
||||
#include "serviceaddresslookup.hpp"
|
||||
|
||||
#include <llarp/path/path_types.hpp>
|
||||
|
||||
namespace llarp::dht
|
||||
{
|
||||
struct LocalServiceAddressLookup : public ServiceAddressLookup
|
||||
{
|
||||
PathID_t localPath;
|
||||
|
||||
LocalServiceAddressLookup(
|
||||
const PathID_t& pathid,
|
||||
uint64_t txid,
|
||||
uint64_t relayOrder,
|
||||
const Key_t& addr,
|
||||
AbstractDHTMessageHandler* ctx,
|
||||
[[maybe_unused]] const Key_t& askpeer);
|
||||
|
||||
void
|
||||
SendReply() override;
|
||||
};
|
||||
|
||||
} // namespace llarp::dht
|
||||
|
||||
#endif
|
@ -1,42 +0,0 @@
|
||||
#include "localtaglookup.hpp"
|
||||
|
||||
#include "context.hpp"
|
||||
#include <llarp/dht/messages/gotintro.hpp>
|
||||
#include <llarp/path/path_context.hpp>
|
||||
#include <llarp/router/router.hpp>
|
||||
#include <llarp/routing/path_dht_message.hpp>
|
||||
|
||||
namespace llarp::dht
|
||||
{
|
||||
LocalTagLookup::LocalTagLookup(
|
||||
const PathID_t& path,
|
||||
uint64_t txid,
|
||||
const service::Tag& _target,
|
||||
AbstractDHTMessageHandler* ctx)
|
||||
: TagLookup(TXOwner{ctx->OurKey(), txid}, _target, ctx, 0), localPath(path)
|
||||
{}
|
||||
|
||||
void
|
||||
LocalTagLookup::SendReply()
|
||||
{
|
||||
auto path =
|
||||
parent->GetRouter()->path_context().GetByUpstream(parent->OurKey().as_array(), localPath);
|
||||
if (!path)
|
||||
{
|
||||
llarp::LogWarn(
|
||||
"did not send reply for relayed dht request, no such local path "
|
||||
"for pathid=",
|
||||
localPath);
|
||||
return;
|
||||
}
|
||||
routing::PathDHTMessage msg;
|
||||
msg.dht_msgs.emplace_back(new GotIntroMessage(valuesFound, whoasked.txid));
|
||||
if (!path->SendRoutingMessage(msg, parent->GetRouter()))
|
||||
{
|
||||
llarp::LogWarn(
|
||||
"failed to send routing message when informing result of dht "
|
||||
"request, pathid=",
|
||||
localPath);
|
||||
}
|
||||
}
|
||||
} // namespace llarp::dht
|
@ -1,23 +0,0 @@
|
||||
#ifndef LLARP_DHT_LOOKUPTAGLOOKUP
|
||||
#define LLARP_DHT_LOOKUPTAGLOOKUP
|
||||
|
||||
#include "taglookup.hpp"
|
||||
|
||||
namespace llarp::dht
|
||||
{
|
||||
struct LocalTagLookup : public TagLookup
|
||||
{
|
||||
PathID_t localPath;
|
||||
|
||||
LocalTagLookup(
|
||||
const PathID_t& path,
|
||||
uint64_t txid,
|
||||
const service::Tag& target,
|
||||
AbstractDHTMessageHandler* ctx);
|
||||
|
||||
void
|
||||
SendReply() override;
|
||||
};
|
||||
} // namespace llarp::dht
|
||||
|
||||
#endif
|
@ -1,138 +0,0 @@
|
||||
#include "context.hpp"
|
||||
#include "oxenc/bt_serialize.h"
|
||||
|
||||
#include <memory>
|
||||
#include <llarp/util/bencode.hpp>
|
||||
#include <llarp/dht/messages/findintro.hpp>
|
||||
#include <llarp/dht/messages/findrouter.hpp>
|
||||
#include <llarp/dht/messages/gotintro.hpp>
|
||||
#include <llarp/dht/messages/gotrouter.hpp>
|
||||
#include <llarp/dht/messages/pubintro.hpp>
|
||||
#include <llarp/dht/messages/findname.hpp>
|
||||
#include <llarp/dht/messages/gotname.hpp>
|
||||
|
||||
namespace llarp::dht
|
||||
{
|
||||
struct MessageDecoder
|
||||
{
|
||||
const Key_t& From;
|
||||
std::unique_ptr<AbstractDHTMessage> msg;
|
||||
bool firstKey = true;
|
||||
bool relayed = false;
|
||||
|
||||
MessageDecoder(const Key_t& from, bool wasRelayed) : From(from), relayed(wasRelayed)
|
||||
{}
|
||||
|
||||
bool
|
||||
operator()(llarp_buffer_t* buffer, llarp_buffer_t* key)
|
||||
{
|
||||
llarp_buffer_t strbuf;
|
||||
// check for empty dict
|
||||
if (!key)
|
||||
return !firstKey;
|
||||
// first key
|
||||
if (firstKey)
|
||||
{
|
||||
if (!(key->startswith("A")))
|
||||
return false;
|
||||
if (!bencode_read_string(buffer, &strbuf))
|
||||
return false;
|
||||
// bad msg size?
|
||||
if (strbuf.sz != 1)
|
||||
return false;
|
||||
llarp::LogDebug("Handle DHT message ", *strbuf.base, " relayed=", relayed);
|
||||
switch (*strbuf.base)
|
||||
{
|
||||
case 'N':
|
||||
msg = std::make_unique<FindNameMessage>(From, Key_t{}, 0);
|
||||
break;
|
||||
case 'M':
|
||||
msg = std::make_unique<GotNameMessage>(From, 0, service::EncryptedName{});
|
||||
break;
|
||||
case 'F':
|
||||
msg = std::make_unique<FindIntroMessage>(From, relayed, 0);
|
||||
break;
|
||||
case 'R':
|
||||
if (relayed)
|
||||
msg = std::make_unique<RelayedFindRouterMessage>(From);
|
||||
else
|
||||
msg = std::make_unique<FindRouterMessage>(From);
|
||||
break;
|
||||
case 'S':
|
||||
msg = std::make_unique<GotRouterMessage>(From, relayed);
|
||||
break;
|
||||
case 'I':
|
||||
msg = std::make_unique<PublishIntroMessage>(From, relayed);
|
||||
break;
|
||||
case 'G':
|
||||
if (relayed)
|
||||
{
|
||||
msg = std::make_unique<RelayedGotIntroMessage>();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = std::make_unique<GotIntroMessage>(From);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
llarp::LogWarn("unknown dht message type: ", (char)*strbuf.base);
|
||||
// bad msg type
|
||||
return false;
|
||||
}
|
||||
firstKey = false;
|
||||
return msg != nullptr;
|
||||
}
|
||||
|
||||
return msg->decode_key(*key, buffer);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<AbstractDHTMessage>
|
||||
DecodeMessage(const Key_t& from, llarp_buffer_t* buf, bool relayed)
|
||||
{
|
||||
MessageDecoder dec(from, relayed);
|
||||
if (!bencode_read_dict(dec, buf))
|
||||
return nullptr;
|
||||
|
||||
return std::move(dec.msg);
|
||||
}
|
||||
|
||||
struct ListDecoder
|
||||
{
|
||||
ListDecoder(
|
||||
bool hasRelayed, const Key_t& from, std::vector<std::unique_ptr<AbstractDHTMessage>>& list)
|
||||
: relayed(hasRelayed), From(from), l(list)
|
||||
{}
|
||||
|
||||
bool relayed;
|
||||
const Key_t& From;
|
||||
std::vector<std::unique_ptr<AbstractDHTMessage>>& l;
|
||||
|
||||
bool
|
||||
operator()(llarp_buffer_t* buffer, bool has)
|
||||
{
|
||||
if (!has)
|
||||
return true;
|
||||
auto msg = DecodeMessage(From, buffer, relayed);
|
||||
if (msg)
|
||||
{
|
||||
l.emplace_back(std::move(msg));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
DecodeMessageList(
|
||||
Key_t from,
|
||||
llarp_buffer_t* buf,
|
||||
std::vector<std::unique_ptr<AbstractDHTMessage>>& list,
|
||||
bool relayed)
|
||||
{
|
||||
ListDecoder dec(relayed, from, list);
|
||||
return bencode_read_list(dec, buf);
|
||||
}
|
||||
} // namespace llarp::dht
|
@ -1,81 +0,0 @@
|
||||
#include "publishservicejob.hpp"
|
||||
|
||||
#include "context.hpp"
|
||||
#include <llarp/dht/messages/pubintro.hpp>
|
||||
#include <llarp/dht/messages/gotintro.hpp>
|
||||
#include <llarp/path/path_context.hpp>
|
||||
#include <llarp/routing/path_dht_message.hpp>
|
||||
#include <llarp/router/router.hpp>
|
||||
|
||||
#include <utility>
|
||||
namespace llarp::dht
|
||||
{
|
||||
PublishServiceJob::PublishServiceJob(
|
||||
const TXOwner& asker,
|
||||
const service::EncryptedIntroSet& introset_,
|
||||
AbstractDHTMessageHandler* ctx,
|
||||
uint64_t relayOrder_)
|
||||
: TX<TXOwner, service::EncryptedIntroSet>(asker, asker, ctx)
|
||||
, relayOrder(relayOrder_)
|
||||
, introset(introset_)
|
||||
{}
|
||||
|
||||
bool
|
||||
PublishServiceJob::Validate(const service::EncryptedIntroSet& value) const
|
||||
{
|
||||
if (value.derivedSigningKey != introset.derivedSigningKey)
|
||||
{
|
||||
llarp::LogWarn("publish introset acknowledgement acked a different service");
|
||||
return false;
|
||||
}
|
||||
const llarp_time_t now = llarp::time_now_ms();
|
||||
return value.verify(now);
|
||||
}
|
||||
|
||||
void
|
||||
PublishServiceJob::Start(const TXOwner& peer)
|
||||
{
|
||||
parent->DHTSendTo(
|
||||
peer.node.as_array(), new PublishIntroMessage(introset, peer.txid, false, relayOrder));
|
||||
}
|
||||
|
||||
void
|
||||
PublishServiceJob::SendReply()
|
||||
{
|
||||
parent->DHTSendTo(whoasked.node.as_array(), new GotIntroMessage({introset}, whoasked.txid));
|
||||
}
|
||||
|
||||
LocalPublishServiceJob::LocalPublishServiceJob(
|
||||
const TXOwner& peer,
|
||||
const PathID_t& fromID,
|
||||
uint64_t _txid,
|
||||
const service::EncryptedIntroSet& introset,
|
||||
AbstractDHTMessageHandler* ctx,
|
||||
uint64_t relayOrder)
|
||||
: PublishServiceJob(peer, introset, ctx, relayOrder), localPath(fromID), txid(_txid)
|
||||
{}
|
||||
|
||||
void
|
||||
LocalPublishServiceJob::SendReply()
|
||||
{
|
||||
auto path =
|
||||
parent->GetRouter()->path_context().GetByUpstream(parent->OurKey().as_array(), localPath);
|
||||
if (!path)
|
||||
{
|
||||
llarp::LogWarn(
|
||||
"did not send reply for relayed dht request, no such local path "
|
||||
"for pathid=",
|
||||
localPath);
|
||||
return;
|
||||
}
|
||||
routing::PathDHTMessage msg;
|
||||
msg.dht_msgs.emplace_back(new GotIntroMessage({introset}, txid));
|
||||
if (!path->SendRoutingMessage(msg, parent->GetRouter()))
|
||||
{
|
||||
llarp::LogWarn(
|
||||
"failed to send routing message when informing result of dht "
|
||||
"request, pathid=",
|
||||
localPath);
|
||||
}
|
||||
}
|
||||
} // namespace llarp::dht
|
@ -1,51 +0,0 @@
|
||||
#ifndef LLARP_DHT_PUBLISHSERVICEJOB
|
||||
#define LLARP_DHT_PUBLISHSERVICEJOB
|
||||
|
||||
#include "tx.hpp"
|
||||
#include "txowner.hpp"
|
||||
#include <llarp/service/address.hpp>
|
||||
#include <llarp/service/intro_set.hpp>
|
||||
|
||||
#include <set>
|
||||
|
||||
namespace llarp::dht
|
||||
{
|
||||
struct PublishServiceJob : public TX<TXOwner, service::EncryptedIntroSet>
|
||||
{
|
||||
uint64_t relayOrder;
|
||||
service::EncryptedIntroSet introset;
|
||||
|
||||
PublishServiceJob(
|
||||
const TXOwner& asker,
|
||||
const service::EncryptedIntroSet& introset,
|
||||
AbstractDHTMessageHandler* ctx,
|
||||
uint64_t relayOrder);
|
||||
|
||||
bool
|
||||
Validate(const service::EncryptedIntroSet& introset) const override;
|
||||
|
||||
void
|
||||
Start(const TXOwner& peer) override;
|
||||
|
||||
void
|
||||
SendReply() override;
|
||||
};
|
||||
|
||||
struct LocalPublishServiceJob : public PublishServiceJob
|
||||
{
|
||||
PathID_t localPath;
|
||||
uint64_t txid;
|
||||
LocalPublishServiceJob(
|
||||
const TXOwner& peer,
|
||||
const PathID_t& fromID,
|
||||
uint64_t txid,
|
||||
const service::EncryptedIntroSet& introset,
|
||||
AbstractDHTMessageHandler* ctx,
|
||||
uint64_t relayOrder);
|
||||
|
||||
void
|
||||
SendReply() override;
|
||||
};
|
||||
} // namespace llarp::dht
|
||||
|
||||
#endif
|
@ -1,71 +0,0 @@
|
||||
#include "recursiverouterlookup.hpp"
|
||||
|
||||
#include "context.hpp"
|
||||
#include <llarp/dht/messages/findrouter.hpp>
|
||||
#include <llarp/dht/messages/gotrouter.hpp>
|
||||
|
||||
#include <llarp/router/router.hpp>
|
||||
#include <llarp/router/rc_lookup_handler.hpp>
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
RecursiveRouterLookup::RecursiveRouterLookup(
|
||||
const TXOwner& _whoasked,
|
||||
const RouterID& _target,
|
||||
AbstractDHTMessageHandler* ctx,
|
||||
RouterLookupHandler result)
|
||||
: TX<RouterID, RouterContact>(_whoasked, _target, ctx), resultHandler(std::move(result))
|
||||
|
||||
{
|
||||
peersAsked.insert(ctx->OurKey());
|
||||
}
|
||||
|
||||
bool
|
||||
RecursiveRouterLookup::Validate(const RouterContact& rc) const
|
||||
{
|
||||
if (!rc.Verify(parent->Now()))
|
||||
{
|
||||
llarp::LogWarn("rc from lookup result is invalid");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveRouterLookup::Start(const TXOwner& peer)
|
||||
{
|
||||
parent->DHTSendTo(peer.node.as_array(), new FindRouterMessage(peer.txid, target));
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveRouterLookup::SendReply()
|
||||
{
|
||||
if (valuesFound.size())
|
||||
{
|
||||
RouterContact found;
|
||||
for (const auto& rc : valuesFound)
|
||||
{
|
||||
if (found.OtherIsNewer(rc) && parent->GetRouter()->rc_lookup_handler().check_rc(rc))
|
||||
found = rc;
|
||||
}
|
||||
valuesFound.clear();
|
||||
valuesFound.emplace_back(found);
|
||||
}
|
||||
if (resultHandler)
|
||||
{
|
||||
resultHandler(valuesFound);
|
||||
}
|
||||
if (whoasked.node != parent->OurKey())
|
||||
{
|
||||
parent->DHTSendTo(
|
||||
whoasked.node.as_array(),
|
||||
new GotRouterMessage({}, whoasked.txid, valuesFound, false),
|
||||
false);
|
||||
}
|
||||
}
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
@ -1,34 +0,0 @@
|
||||
#ifndef LLARP_DHT_RECURSIVEROUTERLOOKUP
|
||||
#define LLARP_DHT_RECURSIVEROUTERLOOKUP
|
||||
|
||||
#include "tx.hpp"
|
||||
|
||||
#include <llarp/router_contact.hpp>
|
||||
#include <llarp/router_id.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
struct RecursiveRouterLookup : public TX<RouterID, RouterContact>
|
||||
{
|
||||
RouterLookupHandler resultHandler;
|
||||
RecursiveRouterLookup(
|
||||
const TXOwner& whoasked,
|
||||
const RouterID& target,
|
||||
AbstractDHTMessageHandler* ctx,
|
||||
RouterLookupHandler result);
|
||||
|
||||
bool
|
||||
Validate(const RouterContact& rc) const override;
|
||||
|
||||
void
|
||||
Start(const TXOwner& peer) override;
|
||||
|
||||
void
|
||||
SendReply() override;
|
||||
};
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -1,70 +0,0 @@
|
||||
#include "serviceaddresslookup.hpp"
|
||||
|
||||
#include <llarp/dht/messages/findintro.hpp>
|
||||
#include <llarp/dht/messages/gotintro.hpp>
|
||||
#include <utility>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
ServiceAddressLookup::ServiceAddressLookup(
|
||||
const TXOwner& asker,
|
||||
const Key_t& addr,
|
||||
AbstractDHTMessageHandler* ctx,
|
||||
uint32_t order,
|
||||
service::EncryptedIntroSetLookupHandler handler)
|
||||
: TX<TXOwner, service::EncryptedIntroSet>(asker, asker, ctx)
|
||||
, location(addr)
|
||||
, handleResult(std::move(handler))
|
||||
, relayOrder(order)
|
||||
{
|
||||
peersAsked.insert(ctx->OurKey());
|
||||
}
|
||||
|
||||
bool
|
||||
ServiceAddressLookup::Validate(const service::EncryptedIntroSet& value) const
|
||||
{
|
||||
if (!value.verify(parent->Now()))
|
||||
{
|
||||
llarp::LogWarn("Got invalid introset from service lookup");
|
||||
return false;
|
||||
}
|
||||
if (value.derivedSigningKey != location)
|
||||
{
|
||||
llarp::LogWarn("got introset with wrong target from service lookup");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ServiceAddressLookup::Start(const TXOwner& peer)
|
||||
{
|
||||
parent->DHTSendTo(
|
||||
peer.node.as_array(), new FindIntroMessage(peer.txid, location, relayOrder));
|
||||
}
|
||||
|
||||
void
|
||||
ServiceAddressLookup::SendReply()
|
||||
{
|
||||
// get newest introset
|
||||
if (valuesFound.size())
|
||||
{
|
||||
llarp::service::EncryptedIntroSet 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));
|
||||
}
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
@ -1,41 +0,0 @@
|
||||
#ifndef LLARP_DHT_SERVICEADDRESSLOOKUP
|
||||
#define LLARP_DHT_SERVICEADDRESSLOOKUP
|
||||
|
||||
#include "key.hpp"
|
||||
#include "tx.hpp"
|
||||
#include <llarp/service/address.hpp>
|
||||
#include <llarp/service/intro_set.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
struct TXOwner;
|
||||
|
||||
struct ServiceAddressLookup : public TX<TXOwner, service::EncryptedIntroSet>
|
||||
{
|
||||
Key_t location;
|
||||
service::EncryptedIntroSetLookupHandler handleResult;
|
||||
uint32_t relayOrder;
|
||||
|
||||
ServiceAddressLookup(
|
||||
const TXOwner& asker,
|
||||
const Key_t& addr,
|
||||
AbstractDHTMessageHandler* ctx,
|
||||
uint32_t relayOrder,
|
||||
service::EncryptedIntroSetLookupHandler handler);
|
||||
|
||||
bool
|
||||
Validate(const service::EncryptedIntroSet& value) const override;
|
||||
|
||||
void
|
||||
Start(const TXOwner& peer) override;
|
||||
|
||||
void
|
||||
SendReply() override;
|
||||
};
|
||||
} // namespace dht
|
||||
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -1,40 +0,0 @@
|
||||
#include "taglookup.hpp"
|
||||
|
||||
#include "context.hpp"
|
||||
#include <llarp/dht/messages/gotintro.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
bool
|
||||
TagLookup::Validate(const service::EncryptedIntroSet& introset) const
|
||||
{
|
||||
if (!introset.verify(parent->Now()))
|
||||
{
|
||||
llarp::LogWarn("got invalid introset from tag lookup");
|
||||
return false;
|
||||
}
|
||||
if (not introset.topic)
|
||||
return false;
|
||||
if (*introset.topic != target)
|
||||
{
|
||||
llarp::LogWarn("got introset with mismatched topic in tag lookup");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TagLookup::Start(const TXOwner& peer)
|
||||
{
|
||||
parent->DHTSendTo(peer.node.as_array(), new FindIntroMessage(target, peer.txid));
|
||||
}
|
||||
|
||||
void
|
||||
TagLookup::SendReply()
|
||||
{
|
||||
parent->DHTSendTo(whoasked.node.as_array(), new GotIntroMessage({}, whoasked.txid));
|
||||
}
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
@ -1,35 +0,0 @@
|
||||
#ifndef LLARP_DHT_TAGLOOKUP
|
||||
#define LLARP_DHT_TAGLOOKUP
|
||||
|
||||
#include "tx.hpp"
|
||||
#include <llarp/service/intro_set.hpp>
|
||||
#include <llarp/service/tag.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
struct TagLookup : public TX<service::Tag, service::EncryptedIntroSet>
|
||||
{
|
||||
uint64_t recursionDepth;
|
||||
TagLookup(
|
||||
const TXOwner& asker,
|
||||
const service::Tag& tag,
|
||||
AbstractDHTMessageHandler* ctx,
|
||||
uint64_t recursion)
|
||||
: TX<service::Tag, service::EncryptedIntroSet>(asker, tag, ctx), recursionDepth(recursion)
|
||||
{}
|
||||
|
||||
bool
|
||||
Validate(const service::EncryptedIntroSet& introset) const override;
|
||||
|
||||
void
|
||||
Start(const TXOwner& peer) override;
|
||||
|
||||
void
|
||||
SendReply() override;
|
||||
};
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -1,364 +0,0 @@
|
||||
#include "exit_messages.hpp"
|
||||
|
||||
#include <llarp/crypto/crypto.hpp>
|
||||
#include <llarp/routing/handler.hpp>
|
||||
|
||||
namespace llarp::routing
|
||||
{
|
||||
bool
|
||||
ObtainExitMessage::Sign(const llarp::SecretKey& sk)
|
||||
{
|
||||
pubkey = seckey_topublic(sk);
|
||||
sig.Zero();
|
||||
|
||||
auto bte = bt_encode();
|
||||
return CryptoManager::instance()->sign(
|
||||
sig, sk, reinterpret_cast<uint8_t*>(bte.data()), bte.size());
|
||||
}
|
||||
|
||||
bool
|
||||
ObtainExitMessage::Verify() const
|
||||
{
|
||||
ObtainExitMessage copy;
|
||||
copy = *this;
|
||||
copy.sig.Zero();
|
||||
|
||||
auto bte = copy.bt_encode();
|
||||
return CryptoManager::instance()->verify(
|
||||
pubkey, reinterpret_cast<uint8_t*>(bte.data()), bte.size(), sig);
|
||||
}
|
||||
|
||||
std::string
|
||||
ObtainExitMessage::bt_encode() const
|
||||
{
|
||||
oxenc::bt_dict_producer btdp;
|
||||
|
||||
try
|
||||
{
|
||||
btdp.append("E", flag);
|
||||
btdp.append("I", pubkey.ToView());
|
||||
btdp.append("S", sequence_number);
|
||||
btdp.append("T", tx_id);
|
||||
btdp.append("Z", sig.ToView());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
log::critical(route_cat, "Error: ObtainExitMessage failed to bt encode contents!");
|
||||
}
|
||||
|
||||
return std::move(btdp).str();
|
||||
}
|
||||
|
||||
bool
|
||||
ObtainExitMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf)
|
||||
{
|
||||
bool read = false;
|
||||
if (!BEncodeMaybeReadDictInt("E", flag, read, k, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictEntry("I", pubkey, read, k, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictInt("T", tx_id, read, k, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictEntry("Z", sig, read, k, buf))
|
||||
return false;
|
||||
return read;
|
||||
}
|
||||
|
||||
bool
|
||||
ObtainExitMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const
|
||||
{
|
||||
return h->HandleObtainExitMessage(*this, r);
|
||||
}
|
||||
|
||||
std::string
|
||||
GrantExitMessage::bt_encode() const
|
||||
{
|
||||
oxenc::bt_dict_producer btdp;
|
||||
|
||||
try
|
||||
{
|
||||
btdp.append("S", sequence_number);
|
||||
btdp.append("T", tx_id);
|
||||
btdp.append("Y", nonce.ToView());
|
||||
btdp.append("Z", sig.ToView());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
log::critical(route_cat, "Error: GrantExitMessage failed to bt encode contents!");
|
||||
}
|
||||
|
||||
return std::move(btdp).str();
|
||||
}
|
||||
|
||||
bool
|
||||
GrantExitMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf)
|
||||
{
|
||||
bool read = false;
|
||||
if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictInt("T", tx_id, read, k, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictEntry("Y", nonce, read, k, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictEntry("Z", sig, read, k, buf))
|
||||
return false;
|
||||
return read;
|
||||
}
|
||||
|
||||
bool
|
||||
GrantExitMessage::Verify(const llarp::PubKey& pk) const
|
||||
{
|
||||
GrantExitMessage copy;
|
||||
copy = *this;
|
||||
copy.sig.Zero();
|
||||
|
||||
auto bte = copy.bt_encode();
|
||||
return CryptoManager::instance()->verify(
|
||||
pk, reinterpret_cast<uint8_t*>(bte.data()), bte.size(), sig);
|
||||
}
|
||||
|
||||
bool
|
||||
GrantExitMessage::Sign(const llarp::SecretKey& sk)
|
||||
{
|
||||
sig.Zero();
|
||||
nonce.Randomize();
|
||||
|
||||
auto bte = bt_encode();
|
||||
return CryptoManager::instance()->sign(
|
||||
sig, sk, reinterpret_cast<uint8_t*>(bte.data()), bte.size());
|
||||
}
|
||||
|
||||
bool
|
||||
GrantExitMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const
|
||||
{
|
||||
return h->HandleGrantExitMessage(*this, r);
|
||||
}
|
||||
|
||||
std::string
|
||||
RejectExitMessage::bt_encode() const
|
||||
{
|
||||
oxenc::bt_dict_producer btdp;
|
||||
|
||||
try
|
||||
{
|
||||
btdp.append("B", backoff_time);
|
||||
btdp.append("S", sequence_number);
|
||||
btdp.append("T", tx_id);
|
||||
btdp.append("Y", nonce.ToView());
|
||||
btdp.append("Z", sig.ToView());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
log::critical(route_cat, "Error: RejectExitMessage failed to bt encode contents!");
|
||||
}
|
||||
|
||||
return std::move(btdp).str();
|
||||
}
|
||||
|
||||
bool
|
||||
RejectExitMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf)
|
||||
{
|
||||
bool read = false;
|
||||
if (!BEncodeMaybeReadDictInt("B", backoff_time, read, k, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictInt("T", tx_id, read, k, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictEntry("Y", nonce, read, k, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictEntry("Z", sig, read, k, buf))
|
||||
return false;
|
||||
return read;
|
||||
}
|
||||
|
||||
bool
|
||||
RejectExitMessage::Sign(const llarp::SecretKey& sk)
|
||||
{
|
||||
sig.Zero();
|
||||
nonce.Randomize();
|
||||
|
||||
auto bte = bt_encode();
|
||||
return CryptoManager::instance()->sign(
|
||||
sig, sk, reinterpret_cast<uint8_t*>(bte.data()), bte.size());
|
||||
}
|
||||
|
||||
bool
|
||||
RejectExitMessage::Verify(const llarp::PubKey& pk) const
|
||||
{
|
||||
RejectExitMessage copy;
|
||||
copy = *this;
|
||||
copy.sig.Zero();
|
||||
|
||||
auto bte = copy.bt_encode();
|
||||
return CryptoManager::instance()->verify(
|
||||
pk, reinterpret_cast<uint8_t*>(bte.data()), bte.size(), sig);
|
||||
}
|
||||
|
||||
bool
|
||||
RejectExitMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const
|
||||
{
|
||||
return h->HandleRejectExitMessage(*this, r);
|
||||
}
|
||||
|
||||
std::string
|
||||
UpdateExitMessage::bt_encode() const
|
||||
{
|
||||
oxenc::bt_dict_producer btdp;
|
||||
|
||||
try
|
||||
{
|
||||
btdp.append("P", path_id.ToView());
|
||||
btdp.append("S", sequence_number);
|
||||
btdp.append("T", tx_id);
|
||||
btdp.append("Z", sig.ToView());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
log::critical(route_cat, "Error: UpdateExitMessage failed to bt encode contents!");
|
||||
}
|
||||
|
||||
return std::move(btdp).str();
|
||||
}
|
||||
|
||||
bool
|
||||
UpdateExitMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf)
|
||||
{
|
||||
bool read = false;
|
||||
if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictInt("T", tx_id, read, k, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictEntry("P", path_id, read, k, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictEntry("Z", sig, read, k, buf))
|
||||
return false;
|
||||
return read;
|
||||
}
|
||||
|
||||
bool
|
||||
UpdateExitMessage::Verify(const llarp::PubKey& pk) const
|
||||
{
|
||||
UpdateExitMessage copy;
|
||||
copy = *this;
|
||||
copy.sig.Zero();
|
||||
|
||||
auto bte = copy.bt_encode();
|
||||
return CryptoManager::instance()->verify(
|
||||
pk, reinterpret_cast<uint8_t*>(bte.data()), bte.size(), sig);
|
||||
}
|
||||
|
||||
bool
|
||||
UpdateExitMessage::Sign(const llarp::SecretKey& sk)
|
||||
{
|
||||
nonce.Randomize();
|
||||
|
||||
auto bte = bt_encode();
|
||||
return CryptoManager::instance()->sign(
|
||||
sig, sk, reinterpret_cast<uint8_t*>(bte.data()), bte.size());
|
||||
}
|
||||
|
||||
bool
|
||||
UpdateExitMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const
|
||||
{
|
||||
return h->HandleUpdateExitMessage(*this, r);
|
||||
}
|
||||
|
||||
std::string
|
||||
UpdateExitVerifyMessage::bt_encode() const
|
||||
{
|
||||
oxenc::bt_dict_producer btdp;
|
||||
|
||||
try
|
||||
{
|
||||
btdp.append("S", sequence_number);
|
||||
btdp.append("T", tx_id);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
log::critical(route_cat, "Error: UpdateExitVerifyMessage failed to bt encode contents!");
|
||||
}
|
||||
|
||||
return std::move(btdp).str();
|
||||
}
|
||||
|
||||
bool
|
||||
UpdateExitVerifyMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf)
|
||||
{
|
||||
bool read = false;
|
||||
if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictInt("T", tx_id, read, k, buf))
|
||||
return false;
|
||||
return read;
|
||||
}
|
||||
|
||||
bool
|
||||
UpdateExitVerifyMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const
|
||||
{
|
||||
return h->HandleUpdateExitVerifyMessage(*this, r);
|
||||
}
|
||||
|
||||
std::string
|
||||
CloseExitMessage::bt_encode() const
|
||||
{
|
||||
oxenc::bt_dict_producer btdp;
|
||||
|
||||
try
|
||||
{
|
||||
btdp.append("S", sequence_number);
|
||||
btdp.append("Y", nonce.ToView());
|
||||
btdp.append("Z", sig.ToView());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
log::critical(route_cat, "Error: CloseExitMessage failed to bt encode contents!");
|
||||
}
|
||||
|
||||
return std::move(btdp).str();
|
||||
}
|
||||
|
||||
bool
|
||||
CloseExitMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf)
|
||||
{
|
||||
bool read = false;
|
||||
if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictEntry("Y", nonce, read, k, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictEntry("Z", sig, read, k, buf))
|
||||
return false;
|
||||
return read;
|
||||
}
|
||||
|
||||
bool
|
||||
CloseExitMessage::Verify(const llarp::PubKey& pk) const
|
||||
{
|
||||
CloseExitMessage copy;
|
||||
copy = *this;
|
||||
copy.sig.Zero();
|
||||
|
||||
auto bte = copy.bt_encode();
|
||||
return CryptoManager::instance()->verify(
|
||||
pk, reinterpret_cast<uint8_t*>(bte.data()), bte.size(), sig);
|
||||
}
|
||||
|
||||
bool
|
||||
CloseExitMessage::Sign(const llarp::SecretKey& sk)
|
||||
{
|
||||
sig.Zero();
|
||||
nonce.Randomize();
|
||||
|
||||
auto bte = bt_encode();
|
||||
return CryptoManager::instance()->sign(
|
||||
sig, sk, reinterpret_cast<uint8_t*>(bte.data()), bte.size());
|
||||
}
|
||||
|
||||
bool
|
||||
CloseExitMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const
|
||||
{
|
||||
return h->HandleCloseExitMessage(*this, r);
|
||||
}
|
||||
} // namespace llarp::routing
|
@ -1,195 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <llarp/crypto/types.hpp>
|
||||
#include "policy.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace llarp::routing
|
||||
{
|
||||
struct ObtainExitMessage final : public AbstractRoutingMessage
|
||||
{
|
||||
uint64_t flag{0}; // 0 for snode, 1 for internet access
|
||||
llarp::PubKey pubkey;
|
||||
uint64_t tx_id{0};
|
||||
llarp::Signature sig;
|
||||
|
||||
ObtainExitMessage() : AbstractRoutingMessage()
|
||||
{}
|
||||
|
||||
~ObtainExitMessage() override = default;
|
||||
|
||||
void
|
||||
clear() override
|
||||
{
|
||||
flag = 0;
|
||||
pubkey.Zero();
|
||||
tx_id = 0;
|
||||
sig.Zero();
|
||||
}
|
||||
|
||||
/// populates I and signs
|
||||
bool
|
||||
Sign(const llarp::SecretKey& sk);
|
||||
|
||||
bool
|
||||
Verify() const;
|
||||
|
||||
std::string
|
||||
bt_encode() const override;
|
||||
|
||||
bool
|
||||
decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override;
|
||||
|
||||
bool
|
||||
handle_message(AbstractRoutingMessageHandler* h, Router* r) const override;
|
||||
};
|
||||
|
||||
struct GrantExitMessage final : public AbstractRoutingMessage
|
||||
{
|
||||
uint64_t tx_id;
|
||||
llarp::AlignedBuffer<16> nonce;
|
||||
llarp::Signature sig;
|
||||
|
||||
std::string
|
||||
bt_encode() const override;
|
||||
|
||||
bool
|
||||
Sign(const llarp::SecretKey& sk);
|
||||
|
||||
bool
|
||||
Verify(const llarp::PubKey& pk) const;
|
||||
|
||||
bool
|
||||
decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override;
|
||||
|
||||
bool
|
||||
handle_message(AbstractRoutingMessageHandler* h, Router* r) const override;
|
||||
|
||||
void
|
||||
clear() override
|
||||
{
|
||||
tx_id = 0;
|
||||
nonce.Zero();
|
||||
sig.Zero();
|
||||
}
|
||||
};
|
||||
|
||||
struct RejectExitMessage final : public AbstractRoutingMessage
|
||||
{
|
||||
uint64_t backoff_time;
|
||||
uint64_t tx_id;
|
||||
llarp::AlignedBuffer<16> nonce;
|
||||
llarp::Signature sig;
|
||||
|
||||
void
|
||||
clear() override
|
||||
{
|
||||
backoff_time = 0;
|
||||
tx_id = 0;
|
||||
nonce.Zero();
|
||||
sig.Zero();
|
||||
}
|
||||
|
||||
bool
|
||||
Sign(const llarp::SecretKey& sk);
|
||||
|
||||
bool
|
||||
Verify(const llarp::PubKey& pk) const;
|
||||
|
||||
std::string
|
||||
bt_encode() const override;
|
||||
|
||||
bool
|
||||
decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override;
|
||||
|
||||
bool
|
||||
handle_message(AbstractRoutingMessageHandler* h, Router* r) const override;
|
||||
};
|
||||
|
||||
struct UpdateExitVerifyMessage final : public AbstractRoutingMessage
|
||||
{
|
||||
uint64_t tx_id;
|
||||
llarp::AlignedBuffer<16> nonce;
|
||||
llarp::Signature sig;
|
||||
|
||||
~UpdateExitVerifyMessage() override = default;
|
||||
|
||||
void
|
||||
clear() override
|
||||
{
|
||||
tx_id = 0;
|
||||
nonce.Zero();
|
||||
sig.Zero();
|
||||
}
|
||||
|
||||
std::string
|
||||
bt_encode() const override;
|
||||
|
||||
bool
|
||||
decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override;
|
||||
|
||||
bool
|
||||
handle_message(AbstractRoutingMessageHandler* h, Router* r) const override;
|
||||
};
|
||||
|
||||
struct UpdateExitMessage final : public AbstractRoutingMessage
|
||||
{
|
||||
llarp::PathID_t path_id;
|
||||
uint64_t tx_id;
|
||||
llarp::AlignedBuffer<16> nonce;
|
||||
llarp::Signature sig;
|
||||
|
||||
bool
|
||||
Sign(const llarp::SecretKey& sk);
|
||||
|
||||
bool
|
||||
Verify(const llarp::PubKey& pk) const;
|
||||
|
||||
std::string
|
||||
bt_encode() const override;
|
||||
|
||||
bool
|
||||
decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override;
|
||||
|
||||
bool
|
||||
handle_message(AbstractRoutingMessageHandler* h, Router* r) const override;
|
||||
|
||||
void
|
||||
clear() override
|
||||
{
|
||||
path_id.Zero();
|
||||
tx_id = 0;
|
||||
nonce.Zero();
|
||||
sig.Zero();
|
||||
}
|
||||
};
|
||||
|
||||
struct CloseExitMessage final : public AbstractRoutingMessage
|
||||
{
|
||||
llarp::AlignedBuffer<16> nonce;
|
||||
llarp::Signature sig;
|
||||
|
||||
std::string
|
||||
bt_encode() const override;
|
||||
|
||||
bool
|
||||
decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override;
|
||||
|
||||
bool
|
||||
handle_message(AbstractRoutingMessageHandler* h, Router* r) const override;
|
||||
|
||||
bool
|
||||
Sign(const llarp::SecretKey& sk);
|
||||
|
||||
bool
|
||||
Verify(const llarp::PubKey& pk) const;
|
||||
|
||||
void
|
||||
clear() override
|
||||
{
|
||||
nonce.Zero();
|
||||
sig.Zero();
|
||||
}
|
||||
};
|
||||
} // namespace llarp::routing
|
@ -1,127 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "link_message.hpp"
|
||||
#include <llarp/routing/handler.hpp>
|
||||
#include <llarp/routing/message.hpp>
|
||||
#include <llarp/util/bencode.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
struct LinkDiscardMessage final : public AbstractLinkMessage
|
||||
{
|
||||
LinkDiscardMessage() : AbstractLinkMessage()
|
||||
{}
|
||||
|
||||
std::string
|
||||
bt_encode() const override
|
||||
{
|
||||
oxenc::bt_dict_producer btdp;
|
||||
|
||||
try
|
||||
{
|
||||
btdp.append("a", "x");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
log::critical(link_cat, "Error: RelayDownstreamMessage failed to bt encode contents!");
|
||||
}
|
||||
|
||||
return std::move(btdp).str();
|
||||
}
|
||||
|
||||
void
|
||||
clear() override
|
||||
{
|
||||
version = 0;
|
||||
}
|
||||
|
||||
const char*
|
||||
name() const override
|
||||
{
|
||||
return "Discard";
|
||||
}
|
||||
|
||||
bool
|
||||
decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override
|
||||
{
|
||||
if (key.startswith("a"))
|
||||
{
|
||||
llarp_buffer_t strbuf;
|
||||
if (!bencode_read_string(buf, &strbuf))
|
||||
return false;
|
||||
if (strbuf.sz != 1)
|
||||
return false;
|
||||
return *strbuf.cur == 'x';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
handle_message(Router* /*router*/) const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
namespace routing
|
||||
{
|
||||
struct DataDiscardMessage final : public AbstractRoutingMessage
|
||||
{
|
||||
PathID_t path_id;
|
||||
|
||||
DataDiscardMessage() = default;
|
||||
|
||||
DataDiscardMessage(const PathID_t& dst, uint64_t s) : path_id(dst)
|
||||
{
|
||||
sequence_number = s;
|
||||
version = llarp::constants::proto_version;
|
||||
}
|
||||
|
||||
void
|
||||
clear() override
|
||||
{
|
||||
version = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
handle_message(AbstractRoutingMessageHandler* h, Router* r) const override
|
||||
{
|
||||
return h->HandleDataDiscardMessage(*this, r);
|
||||
}
|
||||
|
||||
bool
|
||||
decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) override
|
||||
{
|
||||
bool read = false;
|
||||
if (!BEncodeMaybeReadDictEntry("P", path_id, read, k, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictInt("V", version, read, k, buf))
|
||||
return false;
|
||||
return read;
|
||||
}
|
||||
|
||||
std::string
|
||||
bt_encode() const override
|
||||
{
|
||||
oxenc::bt_dict_producer btdp;
|
||||
|
||||
try
|
||||
{
|
||||
btdp.append("A", "D");
|
||||
btdp.append("P", path_id.ToView());
|
||||
btdp.append("S", sequence_number);
|
||||
btdp.append("V", version);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
log::critical(route_cat, "Error: DataDiscardMessage failed to bt encode contents!");
|
||||
}
|
||||
|
||||
return std::move(btdp).str();
|
||||
}
|
||||
};
|
||||
} // namespace routing
|
||||
|
||||
} // namespace llarp
|
@ -1,493 +0,0 @@
|
||||
#include "relay_commit.hpp"
|
||||
#include "relay_status.hpp"
|
||||
|
||||
#include <llarp/crypto/crypto.hpp>
|
||||
#include <llarp/nodedb.hpp>
|
||||
#include <llarp/path/path_context.hpp>
|
||||
#include <llarp/path/transit_hop.hpp>
|
||||
#include <llarp/router/router.hpp>
|
||||
#include <llarp/router/outbound_message_handler.hpp>
|
||||
#include <llarp/routing/path_confirm_message.hpp>
|
||||
#include <llarp/util/bencode.hpp>
|
||||
#include <llarp/util/buffer.hpp>
|
||||
#include <llarp/util/logging.hpp>
|
||||
#include <llarp/util/meta/memfn.hpp>
|
||||
#include <llarp/tooling/path_event.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
bool
|
||||
LR_CommitMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf)
|
||||
{
|
||||
if (key.startswith("c"))
|
||||
{
|
||||
/// so we dont put it into the shitty queue
|
||||
pathid.Fill('c');
|
||||
return BEncodeReadArray(frames, buf);
|
||||
}
|
||||
bool read = false;
|
||||
if (!BEncodeMaybeVerifyVersion("v", version, llarp::constants::proto_version, read, key, buf))
|
||||
return false;
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
void
|
||||
LR_CommitMessage::clear()
|
||||
{
|
||||
std::for_each(frames.begin(), frames.end(), [](auto& f) { f.Clear(); });
|
||||
version = 0;
|
||||
}
|
||||
|
||||
std::string
|
||||
LR_CommitMessage::bt_encode() const
|
||||
{
|
||||
oxenc::bt_dict_producer btdp;
|
||||
|
||||
try
|
||||
{
|
||||
btdp.append("a", "c");
|
||||
{
|
||||
auto sublist = btdp.append_list("c");
|
||||
|
||||
for (auto& f : frames)
|
||||
sublist.append({reinterpret_cast<const char*>(f.data()), f.size()});
|
||||
}
|
||||
|
||||
btdp.append("v", llarp::constants::proto_version);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
log::critical(link_cat, "Error: LR_CommitMessage failed to bt encode contents!");
|
||||
}
|
||||
|
||||
return std::move(btdp).str();
|
||||
}
|
||||
|
||||
bool
|
||||
LR_CommitMessage::handle_message(Router* router) const
|
||||
{
|
||||
if (frames.size() != path::MAX_LEN)
|
||||
{
|
||||
llarp::LogError("LRCM invalid number of records, ", frames.size(), "!=", path::MAX_LEN);
|
||||
return false;
|
||||
}
|
||||
if (!router->path_context().AllowingTransit())
|
||||
{
|
||||
llarp::LogError("got LRCM when not permitting transit");
|
||||
return false;
|
||||
}
|
||||
return AsyncDecrypt(&router->path_context());
|
||||
}
|
||||
|
||||
bool
|
||||
LR_CommitRecord::BEncode(llarp_buffer_t* buf) const
|
||||
{
|
||||
if (!bencode_start_dict(buf))
|
||||
return false;
|
||||
|
||||
if (!BEncodeWriteDictEntry("c", commkey, buf))
|
||||
return false;
|
||||
if (!BEncodeWriteDictEntry("i", nextHop, buf))
|
||||
return false;
|
||||
if (lifetime > 10s && lifetime < path::DEFAULT_LIFETIME)
|
||||
{
|
||||
if (!BEncodeWriteDictInt("i", lifetime.count(), buf))
|
||||
return false;
|
||||
}
|
||||
if (!BEncodeWriteDictEntry("n", tunnelNonce, buf))
|
||||
return false;
|
||||
if (!BEncodeWriteDictEntry("r", rxid, buf))
|
||||
return false;
|
||||
if (!BEncodeWriteDictEntry("t", txid, buf))
|
||||
return false;
|
||||
if (nextRC)
|
||||
{
|
||||
if (!BEncodeWriteDictEntry("u", *nextRC, buf))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (not bencode_write_uint64_entry(buf, "v", 1, llarp::constants::proto_version))
|
||||
return false;
|
||||
if (work and not BEncodeWriteDictEntry("w", *work, buf))
|
||||
return false;
|
||||
|
||||
return bencode_end(buf);
|
||||
}
|
||||
|
||||
bool
|
||||
LR_CommitRecord::OnKey(llarp_buffer_t* buffer, llarp_buffer_t* key)
|
||||
{
|
||||
if (!key)
|
||||
return true;
|
||||
|
||||
bool read = false;
|
||||
|
||||
if (!BEncodeMaybeReadDictEntry("c", commkey, read, *key, buffer))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictEntry("i", nextHop, read, *key, buffer))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictInt("l", lifetime, read, *key, buffer))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictEntry("n", tunnelNonce, read, *key, buffer))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictEntry("r", rxid, read, *key, buffer))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictEntry("t", txid, read, *key, buffer))
|
||||
return false;
|
||||
if (key->startswith("u"))
|
||||
{
|
||||
nextRC = std::make_unique<RouterContact>();
|
||||
return nextRC->BDecode(buffer);
|
||||
}
|
||||
if (!BEncodeMaybeVerifyVersion(
|
||||
"v", version, llarp::constants::proto_version, read, *key, buffer))
|
||||
return false;
|
||||
if (key->startswith("w"))
|
||||
{
|
||||
// check for duplicate
|
||||
if (work)
|
||||
{
|
||||
llarp::LogWarn("duplicate POW in LRCR");
|
||||
return false;
|
||||
}
|
||||
|
||||
work = std::make_unique<PoW>();
|
||||
return bencode_decode_dict(*work, buffer);
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
bool
|
||||
LR_CommitRecord::BDecode(llarp_buffer_t* buf)
|
||||
{
|
||||
return bencode_read_dict(util::memFn(&LR_CommitRecord::OnKey, this), buf);
|
||||
}
|
||||
|
||||
bool
|
||||
LR_CommitRecord::operator==(const LR_CommitRecord& other) const
|
||||
{
|
||||
if (work && other.work)
|
||||
{
|
||||
if (*work != *other.work)
|
||||
return false;
|
||||
}
|
||||
return nextHop == other.nextHop && commkey == other.commkey && txid == other.txid
|
||||
&& rxid == other.rxid;
|
||||
}
|
||||
|
||||
struct LRCMFrameDecrypt
|
||||
{
|
||||
using Context = llarp::path::PathContext;
|
||||
using Hop = llarp::path::TransitHop;
|
||||
using Decrypter = AsyncFrameDecrypter<LRCMFrameDecrypt>;
|
||||
using Decrypter_ptr = std::unique_ptr<Decrypter>;
|
||||
Decrypter_ptr decrypter;
|
||||
std::array<EncryptedFrame, 8> frames;
|
||||
Context* context;
|
||||
// decrypted record
|
||||
LR_CommitRecord record;
|
||||
// the actual hop
|
||||
std::shared_ptr<Hop> hop;
|
||||
|
||||
oxen::quic::Address from_addr;
|
||||
|
||||
LRCMFrameDecrypt(Context* ctx, Decrypter_ptr dec, const LR_CommitMessage* commit)
|
||||
: decrypter(std::move(dec))
|
||||
, frames(commit->frames)
|
||||
, context(ctx)
|
||||
, hop(std::make_shared<Hop>())
|
||||
, from_addr{
|
||||
commit->conn->remote_rc.IsPublicRouter() ? oxen::quic::Address{}
|
||||
: commit->conn->remote_rc.addr}
|
||||
{
|
||||
hop->info.downstream = commit->conn->remote_rc.pubkey;
|
||||
}
|
||||
|
||||
~LRCMFrameDecrypt() = default;
|
||||
|
||||
static void
|
||||
OnForwardLRCMResult(
|
||||
Router* router,
|
||||
std::shared_ptr<path::TransitHop> path,
|
||||
const PathID_t pathid,
|
||||
const RouterID nextHop,
|
||||
const SharedSecret pathKey,
|
||||
SendStatus sendStatus)
|
||||
{
|
||||
uint64_t status = LR_StatusRecord::FAIL_DEST_INVALID;
|
||||
|
||||
switch (sendStatus)
|
||||
{
|
||||
case SendStatus::Success:
|
||||
// do nothing, will forward success message later
|
||||
return;
|
||||
case SendStatus::Timeout:
|
||||
status = LR_StatusRecord::FAIL_TIMEOUT;
|
||||
break;
|
||||
case SendStatus::NoLink:
|
||||
status = LR_StatusRecord::FAIL_CANNOT_CONNECT;
|
||||
break;
|
||||
case SendStatus::InvalidRouter:
|
||||
status = LR_StatusRecord::FAIL_DEST_INVALID;
|
||||
break;
|
||||
case SendStatus::RouterNotFound:
|
||||
status = LR_StatusRecord::FAIL_DEST_UNKNOWN;
|
||||
break;
|
||||
case SendStatus::Congestion:
|
||||
status = LR_StatusRecord::FAIL_CONGESTION;
|
||||
break;
|
||||
default:
|
||||
LogError("llarp::SendStatus value not in enum class");
|
||||
std::abort();
|
||||
break;
|
||||
}
|
||||
router->queue_work([router, path, pathid, nextHop, pathKey, status] {
|
||||
LR_StatusMessage::CreateAndSend(router, path, pathid, nextHop, pathKey, status);
|
||||
});
|
||||
}
|
||||
|
||||
/// this is done from logic thread
|
||||
static void
|
||||
SendLRCM(std::shared_ptr<LRCMFrameDecrypt> self)
|
||||
{
|
||||
if (self->context->HasTransitHop(self->hop->info))
|
||||
{
|
||||
llarp::LogError("duplicate transit hop ", self->hop->info);
|
||||
LR_StatusMessage::CreateAndSend(
|
||||
self->context->router(),
|
||||
self->hop,
|
||||
self->hop->info.rxID,
|
||||
self->hop->info.downstream,
|
||||
self->hop->pathKey,
|
||||
LR_StatusRecord::FAIL_DUPLICATE_HOP);
|
||||
self->hop = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->from_addr.is_addressable())
|
||||
{
|
||||
// only do ip limiting from non service nodes
|
||||
#ifndef LOKINET_HIVE
|
||||
if (self->context->CheckPathLimitHitByIP(self->from_addr.to_string()))
|
||||
{
|
||||
// we hit a limit so tell it to slow tf down
|
||||
llarp::LogError("client path build hit limit ", self->from_addr);
|
||||
OnForwardLRCMResult(
|
||||
self->context->router(),
|
||||
self->hop,
|
||||
self->hop->info.rxID,
|
||||
self->hop->info.downstream,
|
||||
self->hop->pathKey,
|
||||
SendStatus::Congestion);
|
||||
self->hop = nullptr;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (not self->context->router()->PathToRouterAllowed(self->hop->info.upstream))
|
||||
{
|
||||
// we are not allowed to forward it ... now what?
|
||||
llarp::LogError(
|
||||
"path to ",
|
||||
self->hop->info.upstream,
|
||||
"not allowed, dropping build request on the floor");
|
||||
OnForwardLRCMResult(
|
||||
self->context->router(),
|
||||
self->hop,
|
||||
self->hop->info.rxID,
|
||||
self->hop->info.downstream,
|
||||
self->hop->pathKey,
|
||||
SendStatus::InvalidRouter);
|
||||
self->hop = nullptr;
|
||||
return;
|
||||
}
|
||||
// persist sessions to upstream and downstream routers until the commit
|
||||
// ends
|
||||
self->context->router()->persist_connection_until(
|
||||
self->hop->info.downstream, self->hop->ExpireTime() + 10s);
|
||||
self->context->router()->persist_connection_until(
|
||||
self->hop->info.upstream, self->hop->ExpireTime() + 10s);
|
||||
// put hop
|
||||
self->context->PutTransitHop(self->hop);
|
||||
// forward to next hop
|
||||
using std::placeholders::_1;
|
||||
auto func = [self](auto status) {
|
||||
OnForwardLRCMResult(
|
||||
self->context->router(),
|
||||
self->hop,
|
||||
self->hop->info.rxID,
|
||||
self->hop->info.downstream,
|
||||
self->hop->pathKey,
|
||||
status);
|
||||
self->hop = nullptr;
|
||||
};
|
||||
self->context->ForwardLRCM(self->hop->info.upstream, self->frames, func);
|
||||
// trigger idempotent pump to ensure that the build messages propagate
|
||||
self->context->router()->TriggerPump();
|
||||
}
|
||||
|
||||
// this is called from the logic thread
|
||||
static void
|
||||
SendPathConfirm(std::shared_ptr<LRCMFrameDecrypt> self)
|
||||
{
|
||||
// send path confirmation
|
||||
// TODO: other status flags?
|
||||
uint64_t status = LR_StatusRecord::SUCCESS;
|
||||
if (self->context->HasTransitHop(self->hop->info))
|
||||
{
|
||||
status = LR_StatusRecord::FAIL_DUPLICATE_HOP;
|
||||
}
|
||||
else
|
||||
{
|
||||
// persist session to downstream until path expiration
|
||||
self->context->router()->persist_connection_until(
|
||||
self->hop->info.downstream, self->hop->ExpireTime() + 10s);
|
||||
// put hop
|
||||
self->context->PutTransitHop(self->hop);
|
||||
}
|
||||
|
||||
if (!LR_StatusMessage::CreateAndSend(
|
||||
self->context->router(),
|
||||
self->hop,
|
||||
self->hop->info.rxID,
|
||||
self->hop->info.downstream,
|
||||
self->hop->pathKey,
|
||||
status))
|
||||
{
|
||||
llarp::LogError("failed to send path confirmation for ", self->hop->info);
|
||||
}
|
||||
self->hop = nullptr;
|
||||
}
|
||||
|
||||
// TODO: If decryption has succeeded here but we otherwise don't
|
||||
// want to or can't accept the path build request, send
|
||||
// a status message saying as much.
|
||||
static void
|
||||
HandleDecrypted(llarp_buffer_t* buf, std::shared_ptr<LRCMFrameDecrypt> self)
|
||||
{
|
||||
auto now = self->context->router()->now();
|
||||
auto& info = self->hop->info;
|
||||
if (!buf)
|
||||
{
|
||||
llarp::LogError("LRCM decrypt failed from ", info.downstream);
|
||||
self->decrypter = nullptr;
|
||||
return;
|
||||
}
|
||||
buf->cur = buf->base + EncryptedFrameOverheadSize;
|
||||
llarp::LogDebug("decrypted LRCM from ", info.downstream);
|
||||
// successful decrypt
|
||||
if (!self->record.BDecode(buf))
|
||||
{
|
||||
llarp::LogError("malformed frame inside LRCM from ", info.downstream);
|
||||
self->decrypter = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
info.txID = self->record.txid;
|
||||
info.rxID = self->record.rxid;
|
||||
|
||||
if (info.txID.IsZero() || info.rxID.IsZero())
|
||||
{
|
||||
llarp::LogError("LRCM refusing zero pathid");
|
||||
self->decrypter = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
info.upstream = self->record.nextHop;
|
||||
|
||||
// generate path key as we are in a worker thread
|
||||
auto crypto = CryptoManager::instance();
|
||||
if (!crypto->dh_server(
|
||||
self->hop->pathKey,
|
||||
self->record.commkey,
|
||||
self->context->EncryptionSecretKey(),
|
||||
self->record.tunnelNonce))
|
||||
{
|
||||
llarp::LogError("LRCM DH Failed ", info);
|
||||
self->decrypter = nullptr;
|
||||
return;
|
||||
}
|
||||
// generate hash of hop key for nonce mutation
|
||||
crypto->shorthash(self->hop->nonceXOR, self->hop->pathKey.data(), self->hop->pathKey.size());
|
||||
if (self->record.work && self->record.work->IsValid(now))
|
||||
{
|
||||
llarp::LogDebug(
|
||||
"LRCM extended lifetime by ",
|
||||
ToString(self->record.work->extendedLifetime),
|
||||
" for ",
|
||||
info);
|
||||
self->hop->lifetime += self->record.work->extendedLifetime;
|
||||
}
|
||||
else if (self->record.lifetime < path::DEFAULT_LIFETIME && self->record.lifetime > 10s)
|
||||
{
|
||||
self->hop->lifetime = self->record.lifetime;
|
||||
llarp::LogDebug(
|
||||
"LRCM short lifespan set to ", ToString(self->hop->lifetime), " for ", info);
|
||||
}
|
||||
|
||||
// TODO: check if we really want to accept it
|
||||
self->hop->started = now;
|
||||
|
||||
// self->context->router()->NotifyRouterEvent<tooling::PathRequestReceivedEvent>(
|
||||
// self->context->router()->pubkey(), self->hop);
|
||||
|
||||
size_t sz = self->frames[0].size();
|
||||
// shift
|
||||
std::array<EncryptedFrame, 8> frames;
|
||||
frames[0] = self->frames[1];
|
||||
frames[1] = self->frames[2];
|
||||
frames[2] = self->frames[3];
|
||||
frames[3] = self->frames[4];
|
||||
frames[4] = self->frames[5];
|
||||
frames[5] = self->frames[6];
|
||||
frames[6] = self->frames[7];
|
||||
// put our response on the end
|
||||
frames[7] = EncryptedFrame(sz - EncryptedFrameOverheadSize);
|
||||
// random junk for now
|
||||
frames[7].Randomize();
|
||||
self->frames = std::move(frames);
|
||||
if (self->context->HopIsUs(info.upstream))
|
||||
{
|
||||
// we are the farthest hop
|
||||
llarp::LogDebug("We are the farthest hop for ", info);
|
||||
// send a LRSM down the path
|
||||
self->context->loop()->call([self] {
|
||||
SendPathConfirm(self);
|
||||
self->decrypter = nullptr;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// forward upstream
|
||||
// we are still in the worker thread so post job to logic
|
||||
self->context->loop()->call([self] {
|
||||
SendLRCM(self);
|
||||
self->decrypter = nullptr;
|
||||
});
|
||||
}
|
||||
// trigger idempotent pump to ensure that the build messages propagate
|
||||
self->context->router()->TriggerPump();
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
LR_CommitMessage::AsyncDecrypt(llarp::path::PathContext* context) const
|
||||
{
|
||||
auto decrypter = std::make_unique<LRCMFrameDecrypt::Decrypter>(
|
||||
context->EncryptionSecretKey(), &LRCMFrameDecrypt::HandleDecrypted);
|
||||
// copy frames so we own them
|
||||
auto frameDecrypt = std::make_shared<LRCMFrameDecrypt>(context, std::move(decrypter), this);
|
||||
|
||||
// decrypt frames async
|
||||
frameDecrypt->decrypter->AsyncDecrypt(
|
||||
frameDecrypt->frames[0], frameDecrypt, [r = context->router()](auto func) {
|
||||
r->loop()->call([&]() { func(); });
|
||||
});
|
||||
return true;
|
||||
}
|
||||
} // namespace llarp
|
@ -1,325 +0,0 @@
|
||||
#include <llarp/crypto/crypto.hpp>
|
||||
#include <llarp/path/path_context.hpp>
|
||||
#include <llarp/router/router.hpp>
|
||||
#include <llarp/routing/path_confirm_message.hpp>
|
||||
#include <llarp/util/bencode.hpp>
|
||||
#include <llarp/util/buffer.hpp>
|
||||
#include <llarp/util/logging.hpp>
|
||||
#include <llarp/util/meta/memfn.hpp>
|
||||
#include <llarp/tooling/path_event.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
struct LRSM_AsyncHandler : public std::enable_shared_from_this<LRSM_AsyncHandler>
|
||||
{
|
||||
using HopHandler_ptr = std::shared_ptr<llarp::path::AbstractHopHandler>;
|
||||
|
||||
std::array<EncryptedFrame, 8> frames;
|
||||
uint64_t status = 0;
|
||||
HopHandler_ptr hop;
|
||||
Router* router;
|
||||
PathID_t pathid;
|
||||
|
||||
LRSM_AsyncHandler(
|
||||
std::array<EncryptedFrame, 8> _frames,
|
||||
uint64_t _status,
|
||||
HopHandler_ptr _hop,
|
||||
Router* _router,
|
||||
PathID_t pathid)
|
||||
: frames{std::move(_frames)}
|
||||
, status{_status}
|
||||
, hop{std::move(_hop)}
|
||||
, router{_router}
|
||||
, pathid{std::move(pathid)}
|
||||
{}
|
||||
|
||||
~LRSM_AsyncHandler() = default;
|
||||
|
||||
void
|
||||
handle()
|
||||
{
|
||||
router->notify_router_event<tooling::PathStatusReceivedEvent>(
|
||||
router->pubkey(), pathid, status);
|
||||
hop->HandleLRSM(status, frames, router);
|
||||
}
|
||||
|
||||
void
|
||||
queue_handle()
|
||||
{
|
||||
auto func = [self = shared_from_this()] { self->handle(); };
|
||||
router->queue_work(func);
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
LR_StatusMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf)
|
||||
{
|
||||
bool read = false;
|
||||
if (key.startswith("c"))
|
||||
{
|
||||
return BEncodeReadArray(frames, buf);
|
||||
}
|
||||
if (key.startswith("p"))
|
||||
{
|
||||
if (!BEncodeMaybeReadDictEntry("p", pathid, read, key, buf))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (key.startswith("s"))
|
||||
{
|
||||
if (!BEncodeMaybeReadDictInt("s", status, read, key, buf))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (key.startswith("v"))
|
||||
{
|
||||
if (!BEncodeMaybeVerifyVersion("v", version, llarp::constants::proto_version, read, key, buf))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
void
|
||||
LR_StatusMessage::clear()
|
||||
{
|
||||
std::for_each(frames.begin(), frames.end(), [](auto& f) { f.Clear(); });
|
||||
version = 0;
|
||||
status = 0;
|
||||
}
|
||||
|
||||
std::string
|
||||
LR_StatusMessage::bt_encode() const
|
||||
{
|
||||
oxenc::bt_dict_producer btdp;
|
||||
|
||||
try
|
||||
{
|
||||
btdp.append("a", "s");
|
||||
|
||||
{
|
||||
auto sublist = btdp.append_list("c");
|
||||
|
||||
for (auto& f : frames)
|
||||
sublist.append({reinterpret_cast<const char*>(f.data()), f.size()});
|
||||
}
|
||||
|
||||
btdp.append("p", pathid.ToView());
|
||||
btdp.append("s", status);
|
||||
btdp.append("v", llarp::constants::proto_version);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
log::critical(link_cat, "Error: LR_StatusMessage failed to bt encode contents!");
|
||||
}
|
||||
|
||||
return std::move(btdp).str();
|
||||
}
|
||||
|
||||
bool
|
||||
LR_StatusMessage::handle_message(Router* router) const
|
||||
{
|
||||
llarp::LogDebug("Received LR_Status message from (", conn->remote_rc.pubkey, ")");
|
||||
if (frames.size() != path::MAX_LEN)
|
||||
{
|
||||
llarp::LogError("LRSM invalid number of records, ", frames.size(), "!=", path::MAX_LEN);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto path = router->path_context().GetByUpstream(conn->remote_rc.pubkey, pathid);
|
||||
if (not path)
|
||||
{
|
||||
llarp::LogWarn("unhandled LR_Status message: no associated path found pathid=", pathid);
|
||||
return false;
|
||||
}
|
||||
auto handler = std::make_shared<LRSM_AsyncHandler>(frames, status, path, router, pathid);
|
||||
handler->queue_handle();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
LR_StatusMessage::SetDummyFrames()
|
||||
{
|
||||
for (auto& f : frames)
|
||||
f.Randomize();
|
||||
}
|
||||
|
||||
// call this from a worker thread
|
||||
bool
|
||||
LR_StatusMessage::CreateAndSend(
|
||||
Router* router,
|
||||
std::shared_ptr<path::TransitHop> hop,
|
||||
const PathID_t pathid,
|
||||
const RouterID nextHop,
|
||||
const SharedSecret pathKey,
|
||||
uint64_t status)
|
||||
{
|
||||
auto message = std::make_shared<LR_StatusMessage>();
|
||||
|
||||
message->status = status;
|
||||
message->pathid = pathid;
|
||||
|
||||
message->SetDummyFrames();
|
||||
|
||||
message->AddFrame(pathKey, status);
|
||||
|
||||
QueueSendMessage(router, nextHop, message, hop);
|
||||
return true; // can't guarantee delivery here, as far as we know it's fine
|
||||
}
|
||||
|
||||
bool
|
||||
LR_StatusMessage::AddFrame(const SharedSecret& pathKey, uint64_t newStatus)
|
||||
{
|
||||
frames[7] = frames[6];
|
||||
frames[6] = frames[5];
|
||||
frames[5] = frames[4];
|
||||
frames[4] = frames[3];
|
||||
frames[3] = frames[2];
|
||||
frames[2] = frames[1];
|
||||
frames[1] = frames[0];
|
||||
|
||||
auto& frame = frames[0];
|
||||
|
||||
frame.Randomize();
|
||||
|
||||
LR_StatusRecord record;
|
||||
|
||||
record.status = newStatus;
|
||||
record.version = llarp::constants::proto_version;
|
||||
|
||||
llarp_buffer_t buf(frame.data(), frame.size());
|
||||
buf.cur = buf.base + EncryptedFrameOverheadSize;
|
||||
// encode record
|
||||
if (!record.BEncode(&buf))
|
||||
{
|
||||
// failed to encode?
|
||||
LogError(name(), " Failed to generate Status Record");
|
||||
DumpBuffer(buf);
|
||||
return false;
|
||||
}
|
||||
// use ephemeral keypair for frame
|
||||
if (!frame.DoEncrypt(pathKey, true))
|
||||
{
|
||||
LogError(name(), " Failed to encrypt LRSR");
|
||||
DumpBuffer(buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
LR_StatusMessage::QueueSendMessage(
|
||||
Router* router,
|
||||
const RouterID nextHop,
|
||||
std::shared_ptr<LR_StatusMessage> msg,
|
||||
std::shared_ptr<path::TransitHop> hop)
|
||||
{
|
||||
router->loop()->call([router, nextHop, msg = std::move(msg), hop = std::move(hop)] {
|
||||
SendMessage(router, nextHop, msg, hop);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
LR_StatusMessage::SendMessage(
|
||||
Router* router,
|
||||
const RouterID nextHop,
|
||||
std::shared_ptr<LR_StatusMessage> msg,
|
||||
std::shared_ptr<path::TransitHop> hop)
|
||||
{
|
||||
llarp::LogDebug("Attempting to send LR_Status message to (", nextHop, ")");
|
||||
|
||||
auto resultCallback = [hop, router, msg, nextHop](auto status) {
|
||||
if ((msg->status & LR_StatusRecord::SUCCESS) != LR_StatusRecord::SUCCESS
|
||||
or status != SendStatus::Success)
|
||||
{
|
||||
llarp::LogError("Failed to propagate LR_Status message to ", nextHop);
|
||||
hop->QueueDestroySelf(router);
|
||||
}
|
||||
};
|
||||
|
||||
// send the status message to previous hop
|
||||
// if it fails we are hitting a failure case we can't cope with so ... drop.
|
||||
|
||||
// TODO: replace with new message serialization
|
||||
// if (not router->SendToOrQueue(nextHop, *msg, resultCallback))
|
||||
// resultCallback(SendStatus::Congestion);
|
||||
|
||||
// trigger idempotent pump to make sure stuff gets sent
|
||||
router->TriggerPump();
|
||||
}
|
||||
|
||||
bool
|
||||
LR_StatusRecord::BEncode(llarp_buffer_t* buf) const
|
||||
{
|
||||
return bencode_start_dict(buf) && BEncodeWriteDictInt("s", status, buf)
|
||||
&& bencode_write_uint64_entry(buf, "v", 1, llarp::constants::proto_version)
|
||||
&& bencode_end(buf);
|
||||
}
|
||||
|
||||
bool
|
||||
LR_StatusRecord::OnKey(llarp_buffer_t* buffer, llarp_buffer_t* key)
|
||||
{
|
||||
if (!key)
|
||||
return true;
|
||||
|
||||
bool read = false;
|
||||
|
||||
if (!BEncodeMaybeReadDictInt("s", status, read, *key, buffer))
|
||||
return false;
|
||||
if (!BEncodeMaybeVerifyVersion(
|
||||
"v", version, llarp::constants::proto_version, read, *key, buffer))
|
||||
return false;
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
bool
|
||||
LR_StatusRecord::BDecode(llarp_buffer_t* buf)
|
||||
{
|
||||
return bencode_read_dict(util::memFn(&LR_StatusRecord::OnKey, this), buf);
|
||||
}
|
||||
|
||||
bool
|
||||
LR_StatusRecord::operator==(const LR_StatusRecord& other) const
|
||||
{
|
||||
return status == other.status;
|
||||
}
|
||||
|
||||
using namespace std::literals;
|
||||
static constexpr std::array code_strings = {
|
||||
std::make_pair(LR_StatusRecord::SUCCESS, "success"sv),
|
||||
std::make_pair(LR_StatusRecord::FAIL_TIMEOUT, "timeout"sv),
|
||||
std::make_pair(LR_StatusRecord::FAIL_CONGESTION, "congestion"sv),
|
||||
std::make_pair(LR_StatusRecord::FAIL_DEST_UNKNOWN, "destination unknown"sv),
|
||||
std::make_pair(LR_StatusRecord::FAIL_DECRYPT_ERROR, "decrypt error"sv),
|
||||
std::make_pair(LR_StatusRecord::FAIL_MALFORMED_RECORD, "malformed record"sv),
|
||||
std::make_pair(LR_StatusRecord::FAIL_DEST_INVALID, "destination invalid"sv),
|
||||
std::make_pair(LR_StatusRecord::FAIL_CANNOT_CONNECT, "cannot connect"sv),
|
||||
std::make_pair(LR_StatusRecord::FAIL_DUPLICATE_HOP, "duplicate hop"sv)};
|
||||
|
||||
std::string
|
||||
LRStatusCodeToString(uint64_t status)
|
||||
{
|
||||
std::string s = "[";
|
||||
for (const auto& [val, message] : code_strings)
|
||||
{
|
||||
if ((status & val) == val)
|
||||
{
|
||||
if (s.size() > 1)
|
||||
s += ", ";
|
||||
s += message;
|
||||
}
|
||||
}
|
||||
s += ']';
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace llarp
|
@ -1,197 +1,172 @@
|
||||
#include "endpoint_util.hpp"
|
||||
|
||||
#include <llarp/exit/session.hpp>
|
||||
#include "outbound_context.hpp"
|
||||
#include "lookup.hpp"
|
||||
|
||||
#include <llarp/exit/session.hpp>
|
||||
#include <llarp/util/logging.hpp>
|
||||
|
||||
namespace llarp
|
||||
namespace llarp::service
|
||||
{
|
||||
namespace service
|
||||
void
|
||||
EndpointUtil::ExpireSNodeSessions(llarp_time_t now, SNodeConnectionMap& sessions)
|
||||
{
|
||||
void
|
||||
EndpointUtil::ExpireSNodeSessions(llarp_time_t now, SNodeConnectionMap& sessions)
|
||||
auto itr = sessions.begin();
|
||||
while (itr != sessions.end())
|
||||
{
|
||||
auto itr = sessions.begin();
|
||||
while (itr != sessions.end())
|
||||
if (itr->second->ShouldRemove() && itr->second->IsStopped())
|
||||
{
|
||||
if (itr->second->ShouldRemove() && itr->second->IsStopped())
|
||||
{
|
||||
itr = sessions.erase(itr);
|
||||
continue;
|
||||
}
|
||||
// expunge next tick
|
||||
if (itr->second->IsExpired(now))
|
||||
{
|
||||
itr->second->Stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
itr->second->Tick(now);
|
||||
}
|
||||
|
||||
++itr;
|
||||
itr = sessions.erase(itr);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EndpointUtil::ExpirePendingTx(llarp_time_t now, PendingLookupsMap& lookups)
|
||||
{
|
||||
std::vector<std::unique_ptr<IServiceLookup>> timedout;
|
||||
for (auto itr = lookups.begin(); itr != lookups.end();)
|
||||
// expunge next tick
|
||||
if (itr->second->IsExpired(now))
|
||||
{
|
||||
if (!itr->second->IsTimedOut(now))
|
||||
{
|
||||
++itr;
|
||||
continue;
|
||||
}
|
||||
timedout.emplace_back(std::move(itr->second));
|
||||
itr = lookups.erase(itr);
|
||||
itr->second->Stop();
|
||||
}
|
||||
|
||||
for (const auto& lookup : timedout)
|
||||
else
|
||||
{
|
||||
LogWarn(lookup->name, " timed out txid=", lookup->txid);
|
||||
lookup->HandleTimeout();
|
||||
itr->second->Tick(now);
|
||||
}
|
||||
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EndpointUtil::ExpirePendingRouterLookups(llarp_time_t now, PendingRoutersMap& routers)
|
||||
void
|
||||
EndpointUtil::ExpirePendingRouterLookups(llarp_time_t now, PendingRoutersMap& routers)
|
||||
{
|
||||
for (auto itr = routers.begin(); itr != routers.end();)
|
||||
{
|
||||
for (auto itr = routers.begin(); itr != routers.end();)
|
||||
if (!itr->second.IsExpired(now))
|
||||
{
|
||||
if (!itr->second.IsExpired(now))
|
||||
{
|
||||
++itr;
|
||||
continue;
|
||||
}
|
||||
LogWarn("lookup for ", itr->first, " timed out");
|
||||
itr->second.InformResult({});
|
||||
itr = routers.erase(itr);
|
||||
++itr;
|
||||
continue;
|
||||
}
|
||||
LogWarn("lookup for ", itr->first, " timed out");
|
||||
itr->second.InformResult({});
|
||||
itr = routers.erase(itr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EndpointUtil::DeregisterDeadSessions(llarp_time_t now, ConnectionMap& sessions)
|
||||
void
|
||||
EndpointUtil::DeregisterDeadSessions(llarp_time_t now, ConnectionMap& sessions)
|
||||
{
|
||||
auto itr = sessions.begin();
|
||||
while (itr != sessions.end())
|
||||
{
|
||||
auto itr = sessions.begin();
|
||||
while (itr != sessions.end())
|
||||
if (itr->second->IsDone(now))
|
||||
{
|
||||
if (itr->second->IsDone(now))
|
||||
{
|
||||
itr = sessions.erase(itr);
|
||||
}
|
||||
else
|
||||
{
|
||||
++itr;
|
||||
}
|
||||
itr = sessions.erase(itr);
|
||||
}
|
||||
else
|
||||
{
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EndpointUtil::TickRemoteSessions(
|
||||
llarp_time_t now,
|
||||
ConnectionMap& remoteSessions,
|
||||
ConnectionMap& deadSessions,
|
||||
std::unordered_map<ConvoTag, Session>& sessions)
|
||||
void
|
||||
EndpointUtil::TickRemoteSessions(
|
||||
llarp_time_t now,
|
||||
ConnectionMap& remoteSessions,
|
||||
ConnectionMap& deadSessions,
|
||||
std::unordered_map<ConvoTag, Session>& sessions)
|
||||
{
|
||||
auto itr = remoteSessions.begin();
|
||||
while (itr != remoteSessions.end())
|
||||
{
|
||||
auto itr = remoteSessions.begin();
|
||||
while (itr != remoteSessions.end())
|
||||
itr->second->Tick(now);
|
||||
if (itr->second->Pump(now))
|
||||
{
|
||||
itr->second->Tick(now);
|
||||
if (itr->second->Pump(now))
|
||||
{
|
||||
LogInfo(
|
||||
"marking session as dead T=",
|
||||
itr->second->currentConvoTag,
|
||||
" to ",
|
||||
itr->second->Addr());
|
||||
itr->second->Stop();
|
||||
sessions.erase(itr->second->currentConvoTag);
|
||||
deadSessions.emplace(std::move(*itr));
|
||||
itr = remoteSessions.erase(itr);
|
||||
}
|
||||
else
|
||||
{
|
||||
++itr;
|
||||
}
|
||||
LogInfo(
|
||||
"marking session as dead T=",
|
||||
itr->second->get_current_tag(),
|
||||
" to ",
|
||||
itr->second->Addr());
|
||||
itr->second->Stop();
|
||||
sessions.erase(itr->second->get_current_tag());
|
||||
deadSessions.emplace(std::move(*itr));
|
||||
itr = remoteSessions.erase(itr);
|
||||
}
|
||||
for (auto& item : deadSessions)
|
||||
else
|
||||
{
|
||||
item.second->Tick(now);
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
for (auto& item : deadSessions)
|
||||
{
|
||||
item.second->Tick(now);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EndpointUtil::ExpireConvoSessions(
|
||||
llarp_time_t now, std::unordered_map<ConvoTag, Session>& sessions)
|
||||
void
|
||||
EndpointUtil::ExpireConvoSessions(
|
||||
llarp_time_t now, std::unordered_map<ConvoTag, Session>& sessions)
|
||||
{
|
||||
auto itr = sessions.begin();
|
||||
while (itr != sessions.end())
|
||||
{
|
||||
auto itr = sessions.begin();
|
||||
while (itr != sessions.end())
|
||||
if (itr->second.IsExpired(now))
|
||||
{
|
||||
if (itr->second.IsExpired(now))
|
||||
{
|
||||
LogInfo("Expire session T=", itr->first, " to ", itr->second.Addr());
|
||||
itr = sessions.erase(itr);
|
||||
}
|
||||
else
|
||||
++itr;
|
||||
LogInfo("Expire session T=", itr->first, " to ", itr->second.Addr());
|
||||
itr = sessions.erase(itr);
|
||||
}
|
||||
else
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EndpointUtil::StopRemoteSessions(ConnectionMap& remoteSessions)
|
||||
void
|
||||
EndpointUtil::StopRemoteSessions(ConnectionMap& remoteSessions)
|
||||
{
|
||||
for (auto& item : remoteSessions)
|
||||
{
|
||||
for (auto& item : remoteSessions)
|
||||
{
|
||||
item.second->Stop();
|
||||
}
|
||||
item.second->Stop();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EndpointUtil::StopSnodeSessions(SNodeConnectionMap& sessions)
|
||||
void
|
||||
EndpointUtil::StopSnodeSessions(SNodeConnectionMap& sessions)
|
||||
{
|
||||
for (auto& item : sessions)
|
||||
{
|
||||
for (auto& item : sessions)
|
||||
{
|
||||
item.second->Stop();
|
||||
}
|
||||
item.second->Stop();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
EndpointUtil::HasPathToService(const Address& addr, const ConnectionMap& remoteSessions)
|
||||
bool
|
||||
EndpointUtil::HasPathToService(const Address& addr, const ConnectionMap& remoteSessions)
|
||||
{
|
||||
auto range = remoteSessions.equal_range(addr);
|
||||
auto itr = range.first;
|
||||
while (itr != range.second)
|
||||
{
|
||||
auto range = remoteSessions.equal_range(addr);
|
||||
auto itr = range.first;
|
||||
while (itr != range.second)
|
||||
{
|
||||
if (itr->second->ReadyToSend())
|
||||
return true;
|
||||
++itr;
|
||||
}
|
||||
return false;
|
||||
if (itr->second->ReadyToSend())
|
||||
return true;
|
||||
++itr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
EndpointUtil::GetConvoTagsForService(
|
||||
const std::unordered_map<ConvoTag, Session>& sessions,
|
||||
const Address& info,
|
||||
std::set<ConvoTag>& tags)
|
||||
bool
|
||||
EndpointUtil::GetConvoTagsForService(
|
||||
const std::unordered_map<ConvoTag, Session>& sessions,
|
||||
const Address& info,
|
||||
std::set<ConvoTag>& tags)
|
||||
{
|
||||
bool inserted = false;
|
||||
auto itr = sessions.begin();
|
||||
while (itr != sessions.end())
|
||||
{
|
||||
bool inserted = false;
|
||||
auto itr = sessions.begin();
|
||||
while (itr != sessions.end())
|
||||
if (itr->second.remote.Addr() == info)
|
||||
{
|
||||
if (itr->second.remote.Addr() == info)
|
||||
if (tags.emplace(itr->first).second)
|
||||
{
|
||||
if (tags.emplace(itr->first).second)
|
||||
{
|
||||
inserted = true;
|
||||
}
|
||||
inserted = true;
|
||||
}
|
||||
++itr;
|
||||
}
|
||||
return inserted;
|
||||
++itr;
|
||||
}
|
||||
} // namespace service
|
||||
} // namespace llarp
|
||||
return inserted;
|
||||
}
|
||||
} // namespace llarp::service
|
||||
|
@ -1,168 +0,0 @@
|
||||
#include "sendcontext.hpp"
|
||||
|
||||
#include <llarp/path/path.hpp>
|
||||
#include <llarp/router/router.hpp>
|
||||
#include <llarp/routing/path_transfer_message.hpp>
|
||||
#include "endpoint.hpp"
|
||||
#include <utility>
|
||||
#include <unordered_set>
|
||||
#include <llarp/crypto/crypto.hpp>
|
||||
|
||||
namespace llarp::service
|
||||
{
|
||||
static constexpr size_t SendContextQueueSize = 512;
|
||||
|
||||
SendContext::SendContext(
|
||||
ServiceInfo ident, const Introduction& intro, path::PathSet* send, Endpoint* ep)
|
||||
: remoteIdent(std::move(ident))
|
||||
, remoteIntro(intro)
|
||||
, m_PathSet(send)
|
||||
, service_endpoint(ep)
|
||||
, createdAt(ep->Now())
|
||||
{}
|
||||
|
||||
bool
|
||||
SendContext::Send(std::shared_ptr<ProtocolFrameMessage> msg, path::Path_ptr path)
|
||||
{
|
||||
if (path->IsReady()
|
||||
and m_SendQueue.tryPushBack(std::make_pair(
|
||||
std::make_shared<routing::PathTransferMessage>(*msg, remoteIntro.path_id), path))
|
||||
== thread::QueueReturn::Success)
|
||||
{
|
||||
service_endpoint->router()->TriggerPump();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
SendContext::FlushUpstream()
|
||||
{
|
||||
auto r = service_endpoint->router();
|
||||
std::unordered_set<path::Path_ptr, path::Ptr_Hash> flushpaths;
|
||||
auto rttRMS = 0ms;
|
||||
while (auto maybe = m_SendQueue.tryPopFront())
|
||||
{
|
||||
auto& [msg, path] = *maybe;
|
||||
msg->sequence_number = path->NextSeqNo();
|
||||
if (path->SendRoutingMessage(*msg, r))
|
||||
{
|
||||
lastGoodSend = r->now();
|
||||
flushpaths.emplace(path);
|
||||
service_endpoint->ConvoTagTX(msg->protocol_frame_msg.convo_tag);
|
||||
const auto rtt = (path->intro.latency + remoteIntro.latency) * 2;
|
||||
rttRMS += rtt * rtt.count();
|
||||
}
|
||||
}
|
||||
// flush the select path's upstream
|
||||
for (const auto& path : flushpaths)
|
||||
{
|
||||
path->FlushUpstream(r);
|
||||
}
|
||||
if (flushpaths.empty())
|
||||
return;
|
||||
estimatedRTT = std::chrono::milliseconds{
|
||||
static_cast<int64_t>(std::sqrt(rttRMS.count() / flushpaths.size()))};
|
||||
}
|
||||
|
||||
/// send on an established convo tag
|
||||
void
|
||||
SendContext::EncryptAndSendTo(const llarp_buffer_t& payload, ProtocolType t)
|
||||
{
|
||||
SharedSecret shared;
|
||||
auto f = std::make_shared<ProtocolFrameMessage>();
|
||||
f->flag = 0;
|
||||
f->nonce.Randomize();
|
||||
f->convo_tag = currentConvoTag;
|
||||
f->sequence_number = ++sequenceNo;
|
||||
|
||||
auto path = m_PathSet->GetPathByRouter(remoteIntro.router);
|
||||
if (!path)
|
||||
{
|
||||
ShiftIntroRouter(remoteIntro.router);
|
||||
LogWarn(m_PathSet->Name(), " cannot encrypt and send: no path for intro ", remoteIntro);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!service_endpoint->GetCachedSessionKeyFor(f->convo_tag, shared))
|
||||
{
|
||||
LogWarn(
|
||||
m_PathSet->Name(),
|
||||
" could not send, has no cached session key on session T=",
|
||||
f->convo_tag);
|
||||
return;
|
||||
}
|
||||
|
||||
auto m = std::make_shared<ProtocolMessage>();
|
||||
service_endpoint->PutIntroFor(f->convo_tag, remoteIntro);
|
||||
service_endpoint->PutReplyIntroFor(f->convo_tag, path->intro);
|
||||
m->proto = t;
|
||||
if (auto maybe = service_endpoint->GetSeqNoForConvo(f->convo_tag))
|
||||
{
|
||||
m->seqno = *maybe;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogWarn(m_PathSet->Name(), " could not get sequence number for session T=", f->convo_tag);
|
||||
return;
|
||||
}
|
||||
m->introReply = path->intro;
|
||||
f->path_id = m->introReply.path_id;
|
||||
m->sender = service_endpoint->GetIdentity().pub;
|
||||
m->tag = f->convo_tag;
|
||||
m->put_buffer(payload);
|
||||
service_endpoint->router()->queue_work([f, m, shared, path, this] {
|
||||
if (not f->EncryptAndSign(*m, shared, service_endpoint->GetIdentity()))
|
||||
{
|
||||
LogError(m_PathSet->Name(), " failed to sign message");
|
||||
return;
|
||||
}
|
||||
Send(f, path);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
SendContext::AsyncSendAuth(std::function<void(AuthResult)> resultHandler)
|
||||
{
|
||||
if (const auto maybe = service_endpoint->MaybeGetAuthInfoForEndpoint(remoteIdent.Addr()))
|
||||
{
|
||||
// send auth message
|
||||
const llarp_buffer_t authdata{maybe->token};
|
||||
AsyncGenIntro(authdata, ProtocolType::Auth);
|
||||
authResultListener = resultHandler;
|
||||
}
|
||||
else
|
||||
resultHandler({AuthResultCode::eAuthAccepted, "no auth needed"});
|
||||
}
|
||||
|
||||
void
|
||||
SendContext::AsyncEncryptAndSendTo(const llarp_buffer_t& data, ProtocolType protocol)
|
||||
{
|
||||
if (IntroSent())
|
||||
{
|
||||
EncryptAndSendTo(data, protocol);
|
||||
return;
|
||||
}
|
||||
// have we generated the initial intro but not sent it yet? bail here so we don't cause
|
||||
// bullshittery
|
||||
if (IntroGenerated() and not IntroSent())
|
||||
{
|
||||
LogWarn(
|
||||
m_PathSet->Name(),
|
||||
" we have generated an intial handshake but have not sent it yet so we drop a packet "
|
||||
"to prevent bullshittery");
|
||||
return;
|
||||
}
|
||||
const auto maybe = service_endpoint->MaybeGetAuthInfoForEndpoint(remoteIdent.Addr());
|
||||
if (maybe.has_value())
|
||||
{
|
||||
// send auth message
|
||||
const llarp_buffer_t authdata(maybe->token);
|
||||
AsyncGenIntro(authdata, ProtocolType::Auth);
|
||||
}
|
||||
else
|
||||
{
|
||||
AsyncGenIntro(data, protocol);
|
||||
}
|
||||
}
|
||||
} // namespace llarp::service
|
@ -1,85 +0,0 @@
|
||||
#pragma once
|
||||
#include "intro.hpp"
|
||||
#include "protocol.hpp"
|
||||
|
||||
#include <llarp/path/pathset.hpp>
|
||||
#include <llarp/constants/path.hpp>
|
||||
#include <llarp/service/convotag.hpp>
|
||||
#include <llarp/util/buffer.hpp>
|
||||
#include <llarp/util/types.hpp>
|
||||
#include <llarp/util/thread/queue.hpp>
|
||||
|
||||
#include <deque>
|
||||
|
||||
namespace llarp::service
|
||||
{
|
||||
struct ServiceInfo;
|
||||
struct Endpoint;
|
||||
struct Introduction;
|
||||
|
||||
struct SendContext
|
||||
{
|
||||
SendContext(ServiceInfo ident, const Introduction& intro, path::PathSet* send, Endpoint* ep);
|
||||
|
||||
void
|
||||
AsyncEncryptAndSendTo(const llarp_buffer_t& payload, ProtocolType t);
|
||||
|
||||
/// queue send a fully encrypted hidden service frame
|
||||
/// via a path
|
||||
bool
|
||||
Send(std::shared_ptr<ProtocolFrameMessage> f, path::Path_ptr path);
|
||||
|
||||
/// flush upstream traffic when in router thread
|
||||
void
|
||||
FlushUpstream();
|
||||
|
||||
SharedSecret sharedKey;
|
||||
ServiceInfo remoteIdent;
|
||||
Introduction remoteIntro;
|
||||
ConvoTag currentConvoTag;
|
||||
path::PathSet* const m_PathSet;
|
||||
// Endpoint* const m_DataHandler;
|
||||
Endpoint* const service_endpoint;
|
||||
uint64_t sequenceNo = 0;
|
||||
llarp_time_t lastGoodSend = 0s;
|
||||
const llarp_time_t createdAt;
|
||||
llarp_time_t sendTimeout = path::BUILD_TIMEOUT;
|
||||
llarp_time_t connectTimeout = path::BUILD_TIMEOUT * 2;
|
||||
llarp_time_t shiftTimeout = (path::BUILD_TIMEOUT * 5) / 2;
|
||||
llarp_time_t estimatedRTT = 0s;
|
||||
bool markedBad = false;
|
||||
|
||||
std::function<void(AuthResult)> authResultListener;
|
||||
|
||||
virtual bool
|
||||
ShiftIntroduction(bool rebuild = true)
|
||||
{
|
||||
(void)rebuild;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void
|
||||
ShiftIntroRouter(const RouterID) = 0;
|
||||
|
||||
virtual void
|
||||
UpdateIntroSet() = 0;
|
||||
|
||||
virtual void
|
||||
MarkCurrentIntroBad(llarp_time_t now) = 0;
|
||||
|
||||
void
|
||||
AsyncSendAuth(std::function<void(AuthResult)> replyHandler);
|
||||
|
||||
private:
|
||||
virtual bool
|
||||
IntroGenerated() const = 0;
|
||||
virtual bool
|
||||
IntroSent() const = 0;
|
||||
|
||||
void
|
||||
EncryptAndSendTo(const llarp_buffer_t& payload, ProtocolType t);
|
||||
|
||||
virtual void
|
||||
AsyncGenIntro(const llarp_buffer_t& payload, ProtocolType t) = 0;
|
||||
};
|
||||
} // namespace llarp::service
|
@ -1,130 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "router_event.hpp"
|
||||
#include <llarp/dht/key.hpp>
|
||||
#include <llarp/service/intro_set.hpp>
|
||||
#include <llarp/dht/messages/findrouter.hpp>
|
||||
|
||||
namespace tooling
|
||||
{
|
||||
struct PubIntroSentEvent : public RouterEvent
|
||||
{
|
||||
llarp::dht::Key_t introsetPubkey;
|
||||
llarp::RouterID relay;
|
||||
uint64_t relayIndex;
|
||||
|
||||
PubIntroSentEvent(
|
||||
const llarp::RouterID& ourRouter,
|
||||
const llarp::dht::Key_t& introsetPubkey_,
|
||||
const llarp::RouterID& relay_,
|
||||
uint64_t relayIndex_)
|
||||
: RouterEvent("DHT: PubIntroSentEvent", ourRouter, false)
|
||||
, introsetPubkey(introsetPubkey_)
|
||||
, relay(relay_)
|
||||
, relayIndex(relayIndex_)
|
||||
{}
|
||||
|
||||
std::string
|
||||
ToString() const
|
||||
{
|
||||
return RouterEvent::ToString() + " ---- introset pubkey: " + introsetPubkey.ShortHex()
|
||||
+ ", relay: " + relay.ShortString() + ", relayIndex: " + std::to_string(relayIndex);
|
||||
}
|
||||
};
|
||||
|
||||
struct PubIntroReceivedEvent : public RouterEvent
|
||||
{
|
||||
llarp::dht::Key_t from;
|
||||
llarp::dht::Key_t location;
|
||||
uint64_t txid;
|
||||
uint64_t relayOrder;
|
||||
|
||||
PubIntroReceivedEvent(
|
||||
const llarp::RouterID& ourRouter,
|
||||
const llarp::dht::Key_t& from_,
|
||||
const llarp::dht::Key_t& location_,
|
||||
uint64_t txid_,
|
||||
uint64_t relayOrder_)
|
||||
: RouterEvent("DHT: PubIntroReceivedEvent", ourRouter, true)
|
||||
, from(from_)
|
||||
, location(location_)
|
||||
, txid(txid_)
|
||||
, relayOrder(relayOrder_)
|
||||
{}
|
||||
|
||||
std::string
|
||||
ToString() const override
|
||||
{
|
||||
return RouterEvent::ToString() + "from " + from.ShortHex()
|
||||
+ " location=" + location.ShortHex() + " order=" + std::to_string(relayOrder)
|
||||
+ " txid=" + std::to_string(txid);
|
||||
}
|
||||
};
|
||||
|
||||
struct GotIntroReceivedEvent : public RouterEvent
|
||||
{
|
||||
llarp::dht::Key_t From;
|
||||
llarp::service::EncryptedIntroSet Introset;
|
||||
uint64_t RelayOrder;
|
||||
uint64_t TxID;
|
||||
|
||||
GotIntroReceivedEvent(
|
||||
const llarp::RouterID& ourRouter_,
|
||||
const llarp::dht::Key_t& from_,
|
||||
const llarp::service::EncryptedIntroSet& introset_,
|
||||
uint64_t txid_)
|
||||
: RouterEvent("DHT:: GotIntroReceivedEvent", ourRouter_, true)
|
||||
, From(from_)
|
||||
, Introset(introset_)
|
||||
, TxID(txid_)
|
||||
{}
|
||||
|
||||
std::string
|
||||
ToString() const override
|
||||
{
|
||||
return RouterEvent::ToString() + "from " + From.ShortHex()
|
||||
+ " location=" + Introset.derivedSigningKey.ShortHex()
|
||||
+ " order=" + std::to_string(RelayOrder) + " txid=" + std::to_string(TxID);
|
||||
}
|
||||
};
|
||||
|
||||
struct FindRouterEvent : public RouterEvent
|
||||
{
|
||||
llarp::dht::Key_t from;
|
||||
llarp::RouterID targetKey;
|
||||
bool iterative;
|
||||
bool exploritory;
|
||||
uint64_t txid;
|
||||
uint64_t version;
|
||||
|
||||
FindRouterEvent(const llarp::RouterID& ourRouter, const llarp::dht::FindRouterMessage& msg)
|
||||
: RouterEvent("DHT: FindRouterEvent", ourRouter, true)
|
||||
, from(msg.From)
|
||||
, targetKey(msg.targetKey)
|
||||
, iterative(msg.iterative)
|
||||
, exploritory(msg.exploratory)
|
||||
, txid(msg.txid)
|
||||
, version(msg.version)
|
||||
{}
|
||||
|
||||
std::string
|
||||
ToString() const override
|
||||
{
|
||||
return RouterEvent::ToString() + " from " + from.ShortHex()
|
||||
+ ", targetKey: " + targetKey.ToString() + ", iterative: " + std::to_string(iterative)
|
||||
+ ", exploritory " + std::to_string(exploritory) + ", txid " + std::to_string(txid)
|
||||
+ ", version " + std::to_string(version);
|
||||
}
|
||||
};
|
||||
|
||||
struct FindRouterReceivedEvent : public FindRouterEvent
|
||||
{
|
||||
using FindRouterEvent::FindRouterEvent;
|
||||
};
|
||||
|
||||
struct FindRouterSentEvent : public FindRouterEvent
|
||||
{
|
||||
using FindRouterEvent::FindRouterEvent;
|
||||
};
|
||||
|
||||
} // namespace tooling
|
@ -1,30 +0,0 @@
|
||||
#include "hive_context.hpp"
|
||||
|
||||
#include "hive_router.hpp"
|
||||
|
||||
namespace tooling
|
||||
{
|
||||
HiveContext::HiveContext(RouterHive* hive) : m_hive(hive)
|
||||
{}
|
||||
|
||||
std::shared_ptr<llarp::Router>
|
||||
HiveContext::makeRouter(const llarp::EventLoop_ptr& loop)
|
||||
{
|
||||
return std::make_shared<HiveRouter>(loop, makeVPNPlatform(), m_hive);
|
||||
}
|
||||
|
||||
HiveRouter*
|
||||
HiveContext::getRouterAsHiveRouter()
|
||||
{
|
||||
if (not router)
|
||||
return nullptr;
|
||||
|
||||
HiveRouter* hiveRouter = dynamic_cast<HiveRouter*>(router.get());
|
||||
|
||||
if (hiveRouter == nullptr)
|
||||
throw std::runtime_error("HiveContext has a router not of type HiveRouter");
|
||||
|
||||
return hiveRouter;
|
||||
}
|
||||
|
||||
} // namespace tooling
|
@ -1,28 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <llarp.hpp>
|
||||
#include "hive_router.hpp"
|
||||
|
||||
namespace tooling
|
||||
{
|
||||
/// HiveContext is a subclass of llarp::Context which allows RouterHive to
|
||||
/// perform custom behavior which might be undesirable in production code.
|
||||
struct HiveContext : public llarp::Context
|
||||
{
|
||||
HiveContext(RouterHive* hive);
|
||||
|
||||
std::shared_ptr<llarp::Router>
|
||||
makeRouter(const llarp::EventLoop_ptr& loop) override;
|
||||
|
||||
/// Get this context's router as a HiveRouter.
|
||||
///
|
||||
/// Returns nullptr if there is no router or throws an exception if the
|
||||
/// router is somehow not an instance of HiveRouter.
|
||||
HiveRouter*
|
||||
getRouterAsHiveRouter();
|
||||
|
||||
protected:
|
||||
RouterHive* m_hive = nullptr;
|
||||
};
|
||||
|
||||
} // namespace tooling
|
@ -1,36 +0,0 @@
|
||||
#include "hive_router.hpp"
|
||||
|
||||
#include "router_hive.hpp"
|
||||
|
||||
namespace tooling
|
||||
{
|
||||
HiveRouter::HiveRouter(
|
||||
llarp::EventLoop_ptr loop, std::shared_ptr<llarp::vpn::Platform> plat, RouterHive* hive)
|
||||
: Router(loop, plat), m_hive(hive)
|
||||
{}
|
||||
|
||||
bool
|
||||
HiveRouter::disableGossipingRC_TestingOnly()
|
||||
{
|
||||
return m_disableGossiping;
|
||||
}
|
||||
|
||||
void
|
||||
HiveRouter::disableGossiping()
|
||||
{
|
||||
m_disableGossiping = true;
|
||||
}
|
||||
|
||||
void
|
||||
HiveRouter::enableGossiping()
|
||||
{
|
||||
m_disableGossiping = false;
|
||||
}
|
||||
|
||||
void
|
||||
HiveRouter::HandleRouterEvent(RouterEventPtr event) const
|
||||
{
|
||||
m_hive->NotifyEvent(std::move(event));
|
||||
}
|
||||
|
||||
} // namespace tooling
|
@ -1,38 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <llarp/router/router.hpp>
|
||||
|
||||
namespace tooling
|
||||
{
|
||||
/// HiveRouter is a subclass of Router which overrides specific behavior in
|
||||
/// order to perform testing-related functions. It exists largely to prevent
|
||||
/// this behavior (which may often be "dangerous") from leaking into release
|
||||
/// code.
|
||||
struct HiveRouter : public llarp::Router
|
||||
{
|
||||
explicit HiveRouter(
|
||||
llarp::EventLoop_ptr loop,
|
||||
std::shared_ptr<llarp::vpn::Platform> vpnPlatform,
|
||||
RouterHive* hive);
|
||||
|
||||
virtual ~HiveRouter() = default;
|
||||
|
||||
/// Override logic to prevent base Router class from gossiping its RC.
|
||||
virtual bool
|
||||
disableGossipingRC_TestingOnly() override;
|
||||
|
||||
void
|
||||
disableGossiping();
|
||||
|
||||
void
|
||||
enableGossiping();
|
||||
|
||||
protected:
|
||||
bool m_disableGossiping = false;
|
||||
RouterHive* m_hive = nullptr;
|
||||
|
||||
virtual void
|
||||
HandleRouterEvent(RouterEventPtr event) const override;
|
||||
};
|
||||
|
||||
} // namespace tooling
|
@ -1,132 +0,0 @@
|
||||
#include "router_event.hpp"
|
||||
|
||||
#include <llarp/path/path_types.hpp>
|
||||
#include <llarp/path/path.hpp>
|
||||
#include <llarp/path/transit_hop.hpp>
|
||||
|
||||
namespace tooling
|
||||
{
|
||||
struct PathAttemptEvent : public RouterEvent
|
||||
{
|
||||
std::vector<llarp::path::PathHopConfig> hops;
|
||||
llarp::PathID_t pathid;
|
||||
|
||||
PathAttemptEvent(const llarp::RouterID& routerID, std::shared_ptr<const llarp::path::Path> path)
|
||||
: RouterEvent("PathAttemptEvent", routerID, false)
|
||||
, hops(path->hops)
|
||||
, pathid(path->hops[0].rxID)
|
||||
{}
|
||||
|
||||
std::string
|
||||
ToString() const
|
||||
{
|
||||
std::string result = RouterEvent::ToString();
|
||||
result += "---- [";
|
||||
|
||||
size_t i = 0;
|
||||
for (const auto& hop : hops)
|
||||
{
|
||||
i++;
|
||||
|
||||
result += llarp::RouterID(hop.rc.pubkey).ShortString();
|
||||
result += "]";
|
||||
|
||||
if (i != hops.size())
|
||||
{
|
||||
result += " -> [";
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
struct PathRequestReceivedEvent : public RouterEvent
|
||||
{
|
||||
llarp::RouterID prevHop;
|
||||
llarp::RouterID nextHop;
|
||||
llarp::PathID_t txid;
|
||||
llarp::PathID_t rxid;
|
||||
bool isEndpoint = false;
|
||||
|
||||
PathRequestReceivedEvent(
|
||||
const llarp::RouterID& routerID, std::shared_ptr<const llarp::path::TransitHop> hop)
|
||||
: RouterEvent("PathRequestReceivedEvent", routerID, true)
|
||||
, prevHop(hop->info.downstream)
|
||||
, nextHop(hop->info.upstream)
|
||||
, txid(hop->info.txID)
|
||||
, rxid(hop->info.rxID)
|
||||
, isEndpoint(routerID == nextHop ? true : false)
|
||||
{}
|
||||
|
||||
std::string
|
||||
ToString() const
|
||||
{
|
||||
std::string result = RouterEvent::ToString();
|
||||
result += "---- [";
|
||||
result += prevHop.ShortString();
|
||||
result += "] -> [*";
|
||||
result += routerID.ShortString();
|
||||
result += "] -> [";
|
||||
|
||||
if (isEndpoint)
|
||||
{
|
||||
result += "nowhere]";
|
||||
}
|
||||
else
|
||||
{
|
||||
result += nextHop.ShortString();
|
||||
result += "]";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
struct PathStatusReceivedEvent : public RouterEvent
|
||||
{
|
||||
llarp::PathID_t rxid;
|
||||
uint64_t status;
|
||||
|
||||
PathStatusReceivedEvent(
|
||||
const llarp::RouterID& routerID, const llarp::PathID_t rxid_, uint64_t status_)
|
||||
: RouterEvent("PathStatusReceivedEvent", routerID, true), rxid(rxid_), status(status_)
|
||||
{}
|
||||
|
||||
std::string
|
||||
ToString() const
|
||||
{
|
||||
std::string result = RouterEvent::ToString();
|
||||
result += "---- path rxid: " + rxid.ShortHex();
|
||||
result += ", status: " + std::to_string(status);
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
struct PathBuildRejectedEvent : public RouterEvent
|
||||
{
|
||||
llarp::PathID_t rxid;
|
||||
llarp::RouterID rejectedBy;
|
||||
|
||||
PathBuildRejectedEvent(
|
||||
const llarp::RouterID& routerID,
|
||||
const llarp::PathID_t rxid_,
|
||||
const llarp::RouterID& rejectedBy_)
|
||||
: RouterEvent("PathBuildRejectedEvent", routerID, false)
|
||||
, rxid(rxid_)
|
||||
, rejectedBy(rejectedBy_)
|
||||
{}
|
||||
|
||||
std::string
|
||||
ToString() const
|
||||
{
|
||||
std::string result = RouterEvent::ToString();
|
||||
result += "---- path rxid: " + rxid.ShortHex();
|
||||
result += ", rejectedBy: " + rejectedBy.ShortString();
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace tooling
|
@ -1,42 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "router_event.hpp"
|
||||
|
||||
namespace tooling
|
||||
{
|
||||
struct LinkSessionEstablishedEvent : public RouterEvent
|
||||
{
|
||||
llarp::RouterID remoteId;
|
||||
bool inbound = false;
|
||||
|
||||
LinkSessionEstablishedEvent(
|
||||
const llarp::RouterID& ourRouterId, const llarp::RouterID& remoteId_, bool inbound_)
|
||||
: RouterEvent("Link: LinkSessionEstablishedEvent", ourRouterId, false)
|
||||
, remoteId(remoteId_)
|
||||
, inbound(inbound_)
|
||||
{}
|
||||
|
||||
std::string
|
||||
ToString() const
|
||||
{
|
||||
return RouterEvent::ToString() + (inbound ? "inbound" : "outbound")
|
||||
+ " : LinkSessionEstablished with " + remoteId.ToString();
|
||||
}
|
||||
};
|
||||
|
||||
struct ConnectionAttemptEvent : public RouterEvent
|
||||
{
|
||||
llarp::RouterID remoteId;
|
||||
|
||||
ConnectionAttemptEvent(const llarp::RouterID& ourRouterId, const llarp::RouterID& remoteId_)
|
||||
: RouterEvent("Link: ConnectionAttemptEvent", ourRouterId, false), remoteId(remoteId_)
|
||||
{}
|
||||
|
||||
std::string
|
||||
ToString() const
|
||||
{
|
||||
return RouterEvent::ToString() + " : LinkSessionEstablished with " + remoteId.ToString();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace tooling
|
@ -1,53 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "router_event.hpp"
|
||||
|
||||
#include <llarp/router_contact.hpp>
|
||||
|
||||
namespace tooling
|
||||
{
|
||||
struct RCGossipReceivedEvent : public RouterEvent
|
||||
{
|
||||
RCGossipReceivedEvent(const llarp::RouterID& routerID, const llarp::RouterContact& rc_)
|
||||
: RouterEvent("RCGossipReceivedEvent", routerID, true), rc(rc_)
|
||||
{}
|
||||
|
||||
std::string
|
||||
ToString() const override
|
||||
{
|
||||
return RouterEvent::ToString()
|
||||
+ " ---- other RouterID: " + llarp::RouterID(rc.pubkey).ShortString();
|
||||
}
|
||||
|
||||
std::string
|
||||
LongString() const
|
||||
{
|
||||
return RouterEvent::ToString() + " ---- RC: " + rc.ToString();
|
||||
}
|
||||
|
||||
llarp::RouterContact rc;
|
||||
};
|
||||
|
||||
struct RCGossipSentEvent : public RouterEvent
|
||||
{
|
||||
RCGossipSentEvent(const llarp::RouterID& routerID, const llarp::RouterContact& rc_)
|
||||
: RouterEvent("RCGossipSentEvent", routerID, true), rc(rc_)
|
||||
{}
|
||||
|
||||
std::string
|
||||
ToString() const override
|
||||
{
|
||||
return RouterEvent::ToString()
|
||||
+ " ---- sending RC for RouterID: " + llarp::RouterID(rc.pubkey).ShortString();
|
||||
}
|
||||
|
||||
std::string
|
||||
LongString() const
|
||||
{
|
||||
return RouterEvent::ToString() + " ---- RC: " + rc.ToString();
|
||||
}
|
||||
|
||||
llarp::RouterContact rc;
|
||||
};
|
||||
|
||||
} // namespace tooling
|
@ -1,56 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <llarp/router_id.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
struct PathID_t;
|
||||
|
||||
namespace path
|
||||
{
|
||||
struct Path;
|
||||
struct PathHopConfig;
|
||||
|
||||
struct TransitHop;
|
||||
|
||||
} // namespace path
|
||||
|
||||
} // namespace llarp
|
||||
|
||||
namespace tooling
|
||||
{
|
||||
struct RouterHive;
|
||||
|
||||
struct RouterEvent
|
||||
{
|
||||
RouterEvent(std::string eventType, llarp::RouterID routerID, bool triggered)
|
||||
: eventType(eventType), routerID(routerID), triggered(triggered)
|
||||
{}
|
||||
|
||||
virtual ~RouterEvent() = default;
|
||||
|
||||
virtual std::string
|
||||
ToString() const
|
||||
{
|
||||
std::string result;
|
||||
result += eventType;
|
||||
result += " [";
|
||||
result += routerID.ShortString();
|
||||
result += "] -- ";
|
||||
return result;
|
||||
}
|
||||
|
||||
const std::string eventType;
|
||||
|
||||
llarp::RouterID routerID;
|
||||
|
||||
bool triggered = false;
|
||||
};
|
||||
|
||||
using RouterEventPtr = std::unique_ptr<RouterEvent>;
|
||||
|
||||
} // namespace tooling
|
@ -1,249 +0,0 @@
|
||||
#include "router_hive.hpp"
|
||||
|
||||
#include <llarp.hpp>
|
||||
#include <llarp/util/str.hpp>
|
||||
#include <llarp/router/router.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <algorithm>
|
||||
#include <csignal>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace tooling
|
||||
{
|
||||
void
|
||||
RouterHive::AddRouter(const std::shared_ptr<llarp::Config>& config, bool isSNode)
|
||||
{
|
||||
auto& container = (isSNode ? relays : clients);
|
||||
|
||||
llarp::RuntimeOptions opts;
|
||||
opts.isSNode = isSNode;
|
||||
|
||||
Context_ptr context = std::make_shared<HiveContext>(this);
|
||||
context->Configure(config);
|
||||
context->Setup(opts);
|
||||
|
||||
auto routerId = llarp::RouterID(context->router->pubkey());
|
||||
container[routerId] = context;
|
||||
fmt::print("Generated router with ID {}\n", routerId);
|
||||
}
|
||||
|
||||
void
|
||||
RouterHive::AddRelay(const std::shared_ptr<llarp::Config>& config)
|
||||
{
|
||||
AddRouter(config, true);
|
||||
}
|
||||
|
||||
void
|
||||
RouterHive::AddClient(const std::shared_ptr<llarp::Config>& config)
|
||||
{
|
||||
AddRouter(config, false);
|
||||
}
|
||||
|
||||
void
|
||||
RouterHive::StartRouters(bool isRelay)
|
||||
{
|
||||
auto& container = (isRelay ? relays : clients);
|
||||
|
||||
for (const auto& [routerId, ctx] : container)
|
||||
{
|
||||
routerMainThreads.emplace_back([ctx = ctx, isRelay = isRelay]() {
|
||||
ctx->Run(llarp::RuntimeOptions{false, false, isRelay});
|
||||
});
|
||||
std::this_thread::sleep_for(2ms);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RouterHive::StartRelays()
|
||||
{
|
||||
StartRouters(true);
|
||||
}
|
||||
|
||||
void
|
||||
RouterHive::StartClients()
|
||||
{
|
||||
StartRouters(false);
|
||||
}
|
||||
|
||||
void
|
||||
RouterHive::StopRouters()
|
||||
{
|
||||
llarp::LogInfo("Signalling all routers to stop");
|
||||
for (auto& [routerId, ctx] : relays)
|
||||
{
|
||||
ctx->loop->call([ctx = ctx]() { ctx->HandleSignal(SIGINT); });
|
||||
}
|
||||
for (auto& [routerId, ctx] : clients)
|
||||
{
|
||||
ctx->loop->call([ctx = ctx]() { ctx->HandleSignal(SIGINT); });
|
||||
}
|
||||
|
||||
llarp::LogInfo("Waiting on routers to be stopped");
|
||||
for (auto [routerId, ctx] : relays)
|
||||
{
|
||||
while (ctx->IsUp())
|
||||
{
|
||||
std::this_thread::sleep_for(10ms);
|
||||
}
|
||||
}
|
||||
for (auto [routerId, ctx] : clients)
|
||||
{
|
||||
while (ctx->IsUp())
|
||||
{
|
||||
std::this_thread::sleep_for(10ms);
|
||||
}
|
||||
}
|
||||
|
||||
llarp::LogInfo("Joining all router threads");
|
||||
for (auto& thread : routerMainThreads)
|
||||
{
|
||||
while (not thread.joinable())
|
||||
{
|
||||
std::this_thread::sleep_for(500ms);
|
||||
}
|
||||
thread.join();
|
||||
}
|
||||
|
||||
llarp::LogInfo("RouterHive::StopRouters finished");
|
||||
}
|
||||
|
||||
void
|
||||
RouterHive::NotifyEvent(RouterEventPtr event)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard{eventQueueMutex};
|
||||
|
||||
eventQueue.push_back(std::move(event));
|
||||
}
|
||||
|
||||
RouterEventPtr
|
||||
RouterHive::GetNextEvent()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard{eventQueueMutex};
|
||||
|
||||
if (not eventQueue.empty())
|
||||
{
|
||||
auto ptr = std::move(eventQueue.front());
|
||||
eventQueue.pop_front();
|
||||
return ptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::deque<RouterEventPtr>
|
||||
RouterHive::GetAllEvents()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard{eventQueueMutex};
|
||||
|
||||
std::deque<RouterEventPtr> events;
|
||||
if (not eventQueue.empty())
|
||||
{
|
||||
eventQueue.swap(events);
|
||||
}
|
||||
return events;
|
||||
}
|
||||
|
||||
void
|
||||
RouterHive::VisitRouter(Context_ptr ctx, std::function<void(Context_ptr)> visit)
|
||||
{
|
||||
// TODO: this should be called from each router's appropriate Loop, e.g.:
|
||||
// ctx->loop->call([visit, ctx]() { visit(ctx); });
|
||||
// however, this causes visit calls to be deferred
|
||||
visit(ctx);
|
||||
}
|
||||
|
||||
HiveRouter*
|
||||
RouterHive::GetRelay(const llarp::RouterID& id, bool needMutexLock)
|
||||
{
|
||||
auto guard =
|
||||
needMutexLock ? std::make_optional<std::lock_guard<std::mutex>>(routerMutex) : std::nullopt;
|
||||
|
||||
auto itr = relays.find(id);
|
||||
if (itr == relays.end())
|
||||
return nullptr;
|
||||
|
||||
auto ctx = itr->second;
|
||||
return ctx->getRouterAsHiveRouter();
|
||||
}
|
||||
|
||||
std::vector<size_t>
|
||||
RouterHive::RelayConnectedRelays()
|
||||
{
|
||||
std::lock_guard guard{routerMutex};
|
||||
std::vector<size_t> results;
|
||||
results.resize(relays.size());
|
||||
std::mutex results_lock;
|
||||
|
||||
size_t i = 0;
|
||||
size_t done_count = 0;
|
||||
for (auto& [routerId, ctx] : relays)
|
||||
{
|
||||
ctx->loop->call([&, i, ctx = ctx]() {
|
||||
size_t count = ctx->router->NumberOfConnectedRouters();
|
||||
std::lock_guard guard{results_lock};
|
||||
results[i] = count;
|
||||
done_count++;
|
||||
});
|
||||
i++;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
size_t read_done_count = 0;
|
||||
{
|
||||
std::lock_guard guard{results_lock};
|
||||
read_done_count = done_count;
|
||||
}
|
||||
if (read_done_count == relays.size())
|
||||
break;
|
||||
|
||||
std::this_thread::sleep_for(100ms);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
// TODO: DRY -- this smells a lot like RelayConnectedRelays()
|
||||
std::vector<llarp::RouterContact>
|
||||
RouterHive::GetRelayRCs()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard{routerMutex};
|
||||
std::vector<llarp::RouterContact> results;
|
||||
results.resize(relays.size());
|
||||
|
||||
size_t i = 0;
|
||||
for (auto [routerId, ctx] : relays)
|
||||
{
|
||||
results[i] = ctx->router->rc();
|
||||
i++;
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
void
|
||||
RouterHive::ForEachRelay(std::function<void(Context_ptr)> visit)
|
||||
{
|
||||
for (auto [routerId, ctx] : relays)
|
||||
{
|
||||
VisitRouter(ctx, visit);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RouterHive::ForEachClient(std::function<void(Context_ptr)> visit)
|
||||
{
|
||||
for (auto [routerId, ctx] : clients)
|
||||
{
|
||||
VisitRouter(ctx, visit);
|
||||
}
|
||||
}
|
||||
|
||||
/// safely visit every router context
|
||||
void
|
||||
RouterHive::ForEachRouter(std::function<void(Context_ptr)> visit)
|
||||
{
|
||||
ForEachRelay(visit);
|
||||
ForEachClient(visit);
|
||||
}
|
||||
|
||||
} // namespace tooling
|
@ -1,95 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "router_event.hpp"
|
||||
|
||||
#include <llarp.hpp>
|
||||
#include <llarp/config/config.hpp>
|
||||
#include <llarp/tooling/hive_context.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
struct llarp_config;
|
||||
struct llarp_main;
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
struct Context;
|
||||
} // namespace llarp
|
||||
|
||||
namespace tooling
|
||||
{
|
||||
struct HiveRouter; // Hive's version of Router
|
||||
|
||||
struct RouterHive
|
||||
{
|
||||
using Context_ptr = std::shared_ptr<HiveContext>;
|
||||
|
||||
private:
|
||||
void
|
||||
StartRouters(bool isRelay);
|
||||
|
||||
void
|
||||
AddRouter(const std::shared_ptr<llarp::Config>& config, bool isRelay);
|
||||
|
||||
/// safely visit router (asynchronously)
|
||||
void
|
||||
VisitRouter(Context_ptr ctx, std::function<void(Context_ptr)> visit);
|
||||
|
||||
public:
|
||||
RouterHive() = default;
|
||||
|
||||
void
|
||||
AddRelay(const std::shared_ptr<llarp::Config>& conf);
|
||||
|
||||
void
|
||||
AddClient(const std::shared_ptr<llarp::Config>& conf);
|
||||
|
||||
void
|
||||
StartRelays();
|
||||
|
||||
void
|
||||
StartClients();
|
||||
|
||||
void
|
||||
StopRouters();
|
||||
|
||||
void
|
||||
NotifyEvent(RouterEventPtr event);
|
||||
|
||||
RouterEventPtr
|
||||
GetNextEvent();
|
||||
|
||||
std::deque<RouterEventPtr>
|
||||
GetAllEvents();
|
||||
|
||||
// functions to safely visit each relay and/or client's HiveContext
|
||||
void
|
||||
ForEachRelay(std::function<void(Context_ptr)> visit);
|
||||
void
|
||||
ForEachClient(std::function<void(Context_ptr)> visit);
|
||||
void
|
||||
ForEachRouter(std::function<void(Context_ptr)> visit);
|
||||
|
||||
HiveRouter*
|
||||
GetRelay(const llarp::RouterID& id, bool needMutexLock = true);
|
||||
|
||||
std::vector<size_t>
|
||||
RelayConnectedRelays();
|
||||
|
||||
std::vector<llarp::RouterContact>
|
||||
GetRelayRCs();
|
||||
|
||||
std::mutex routerMutex;
|
||||
std::unordered_map<llarp::RouterID, Context_ptr> relays;
|
||||
std::unordered_map<llarp::RouterID, Context_ptr> clients;
|
||||
|
||||
std::vector<std::thread> routerMainThreads;
|
||||
|
||||
std::mutex eventQueueMutex;
|
||||
std::deque<RouterEventPtr> eventQueue;
|
||||
};
|
||||
|
||||
} // namespace tooling
|
Loading…
Reference in New Issue