mirror of
https://github.com/oxen-io/lokinet
synced 2023-12-14 06:53:00 +01:00
pathfinder interface design
This commit is contained in:
parent
9e502a5beb
commit
e88a1102e2
3 changed files with 314 additions and 0 deletions
52
include/llarp/pathfinder.h
Normal file
52
include/llarp/pathfinder.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
#ifndef LLARP_PATHFINDER_H_
|
||||
#define LLARP_PATHFINDER_H_
|
||||
|
||||
#include <llarp/buffer.h>
|
||||
#include <llarp/router.h>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* path_base.h
|
||||
*
|
||||
* path api functions
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// fwd declr
|
||||
struct llarp_pathfinder_context;
|
||||
|
||||
/// alloc
|
||||
struct llarp_pathfinder_context *
|
||||
llarp_pathfinder_context_new(struct llarp_router* router,
|
||||
struct llarp_dht_context* dht);
|
||||
/// dealloc
|
||||
void
|
||||
llarp_pathfinder_context_free(struct llarp_pathfinder_context* ctx);
|
||||
|
||||
// fwd declr
|
||||
struct llarp_get_route;
|
||||
|
||||
/// response callback
|
||||
typedef void (*llarp_pathfinder_response)(struct llarp_get_route *);
|
||||
|
||||
// request struct
|
||||
struct llarp_get_route
|
||||
{
|
||||
// context
|
||||
struct llarp_pathfinder_context* pathfinder;
|
||||
// parameter
|
||||
byte_t destination[PUBKEYSIZE];
|
||||
// result
|
||||
std::vector<llarp_rc> route;
|
||||
};
|
||||
/// request func
|
||||
// or find_path but thought pathfinder_find_path was a bit redundant
|
||||
void llarp_pathfinder_get_route(struct llarp_pathfinder_context* pathfinder);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
250
llarp/pathfinder.cpp
Normal file
250
llarp/pathfinder.cpp
Normal file
|
@ -0,0 +1,250 @@
|
|||
#include <deque>
|
||||
#include <llarp/encrypted_frame.hpp>
|
||||
#include <llarp/path.hpp>
|
||||
#include "router.hpp"
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
PathContext::PathContext(llarp_router* router)
|
||||
: m_Router(router), m_AllowTransit(false)
|
||||
{
|
||||
}
|
||||
|
||||
PathContext::~PathContext()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
PathContext::AllowTransit()
|
||||
{
|
||||
m_AllowTransit = true;
|
||||
}
|
||||
|
||||
struct LRCMFrameDecrypt
|
||||
{
|
||||
typedef AsyncFrameDecrypter< LRCMFrameDecrypt > Decrypter;
|
||||
Decrypter* decrypter;
|
||||
std::deque< EncryptedFrame > frames;
|
||||
std::deque< EncryptedAck > acks;
|
||||
EncryptedFrame lastFrame;
|
||||
PathContext* context;
|
||||
RouterID from;
|
||||
LR_CommitRecord record;
|
||||
TransitHopInfo info;
|
||||
TransitHop hop;
|
||||
|
||||
LRCMFrameDecrypt(PathContext* ctx, Decrypter* dec,
|
||||
const LR_CommitMessage* commit)
|
||||
: decrypter(dec)
|
||||
, lastFrame(commit->lasthopFrame)
|
||||
, context(ctx)
|
||||
, from(commit->remote)
|
||||
{
|
||||
for(const auto& f : commit->frames)
|
||||
frames.push_front(f);
|
||||
for(const auto& a : commit->acks)
|
||||
acks.push_front(a);
|
||||
}
|
||||
|
||||
~LRCMFrameDecrypt()
|
||||
{
|
||||
delete decrypter;
|
||||
}
|
||||
|
||||
static void
|
||||
AcceptLRCM(void* user)
|
||||
{
|
||||
LRCMFrameDecrypt* self = static_cast< LRCMFrameDecrypt* >(user);
|
||||
llarp::Info("Accepted ", self->info);
|
||||
self->context->PutPendingRelayCommit(self->info.upstream, self->info.txID,
|
||||
self->info, self->hop);
|
||||
size_t sz = self->frames.front().size;
|
||||
// we pop the front element it was ours
|
||||
self->frames.pop_front();
|
||||
// put random on the end
|
||||
// TODO: should this be an encrypted frame?
|
||||
// TODO: should we change the size?
|
||||
self->frames.emplace_back(sz);
|
||||
self->frames.back().Randomize();
|
||||
self->context->ForwardLRCM(self->info.upstream, self->frames, self->acks,
|
||||
self->lastFrame);
|
||||
delete self;
|
||||
}
|
||||
|
||||
static void
|
||||
HandleDecrypted(llarp_buffer_t* buf, LRCMFrameDecrypt* self)
|
||||
{
|
||||
if(!buf)
|
||||
{
|
||||
llarp::Error("LRCM decrypt failed from ", self->from);
|
||||
delete self;
|
||||
return;
|
||||
}
|
||||
llarp::Debug("decrypted LRCM from ", self->from);
|
||||
// successful decrypt
|
||||
if(!self->record.BDecode(buf))
|
||||
{
|
||||
llarp::Error("malformed frame inside LRCM from ", self->from);
|
||||
delete self;
|
||||
return;
|
||||
}
|
||||
self->info = TransitHopInfo(self->from, self->record);
|
||||
if(self->context->HasTransitHop(self->info))
|
||||
{
|
||||
llarp::Error("duplicate transit hop ", self->info);
|
||||
delete self;
|
||||
return;
|
||||
}
|
||||
// choose rx id
|
||||
// TODO: check for duplicates
|
||||
self->info.rxID.Randomize();
|
||||
|
||||
// generate tx key as we are in a worker thread
|
||||
auto DH = self->context->Crypto()->dh_server;
|
||||
if(!DH(self->hop.txKey, self->record.commkey,
|
||||
self->context->EncryptionSecretKey(), self->record.tunnelNonce))
|
||||
{
|
||||
llarp::Error("LRCM DH Failed ", self->info);
|
||||
delete self;
|
||||
return;
|
||||
}
|
||||
if(self->context->HopIsUs(self->record.nextHop))
|
||||
{
|
||||
// we are the farthest hop
|
||||
llarp::Info("We are the farthest hop for ", self->info);
|
||||
// TODO: implement
|
||||
delete self;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: generate rx path
|
||||
|
||||
// forward upstream
|
||||
// XXX: we are still in the worker thread so post job to logic
|
||||
llarp_logic_queue_job(self->context->Logic(), {self, &AcceptLRCM});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
PathContext::HandleRelayCommit(const LR_CommitMessage* commit)
|
||||
{
|
||||
if(!m_AllowTransit)
|
||||
{
|
||||
llarp::Error("got LRCM from ", commit->remote,
|
||||
" when not allowing transit traffic");
|
||||
return false;
|
||||
}
|
||||
if(commit->frames.size() <= 1)
|
||||
{
|
||||
llarp::Error("got LRCM with too few frames from ", commit->remote);
|
||||
return false;
|
||||
}
|
||||
LRCMFrameDecrypt::Decrypter* decrypter =
|
||||
new LRCMFrameDecrypt::Decrypter(&m_Router->crypto, m_Router->encryption,
|
||||
&LRCMFrameDecrypt::HandleDecrypted);
|
||||
// copy frames so we own them
|
||||
LRCMFrameDecrypt* frames = new LRCMFrameDecrypt(this, decrypter, commit);
|
||||
|
||||
// decrypt frames async
|
||||
decrypter->AsyncDecrypt(m_Router->tp, &frames->frames.front(), frames);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
llarp_threadpool*
|
||||
PathContext::Worker()
|
||||
{
|
||||
return m_Router->tp;
|
||||
}
|
||||
|
||||
llarp_crypto*
|
||||
PathContext::Crypto()
|
||||
{
|
||||
return &m_Router->crypto;
|
||||
}
|
||||
|
||||
llarp_logic*
|
||||
PathContext::Logic()
|
||||
{
|
||||
return m_Router->logic;
|
||||
}
|
||||
|
||||
byte_t*
|
||||
PathContext::EncryptionSecretKey()
|
||||
{
|
||||
return m_Router->encryption;
|
||||
}
|
||||
|
||||
bool
|
||||
PathContext::HopIsUs(const PubKey& k) const
|
||||
{
|
||||
return memcmp(k, m_Router->pubkey(), PUBKEYSIZE) == 0;
|
||||
}
|
||||
|
||||
bool
|
||||
PathContext::ForwardLRCM(const RouterID& nextHop,
|
||||
std::deque< EncryptedFrame >& frames,
|
||||
std::deque< EncryptedAck >& acks,
|
||||
EncryptedFrame& lastHop)
|
||||
{
|
||||
LR_CommitMessage* msg = new LR_CommitMessage;
|
||||
while(frames.size())
|
||||
{
|
||||
msg->frames.push_back(frames.back());
|
||||
frames.pop_back();
|
||||
}
|
||||
while(acks.size())
|
||||
{
|
||||
msg->acks.push_back(acks.back());
|
||||
acks.pop_back();
|
||||
}
|
||||
msg->lasthopFrame = lastHop;
|
||||
return m_Router->SendToOrQueue(nextHop, {msg});
|
||||
}
|
||||
|
||||
template < typename Map_t, typename Value_t >
|
||||
bool
|
||||
MapHas(Map_t& map, const Value_t& val)
|
||||
{
|
||||
std::unique_lock< std::mutex > lock(map.first);
|
||||
return map.second.find(val) != map.second.end();
|
||||
}
|
||||
|
||||
template < typename Map_t, typename Key_t, typename Value_t >
|
||||
void
|
||||
MapPut(Map_t& map, const Key_t& k, const Value_t& v)
|
||||
{
|
||||
std::unique_lock< std::mutex > lock(map.first);
|
||||
map.second[k] = v;
|
||||
}
|
||||
|
||||
bool
|
||||
PathContext::HasTransitHop(const TransitHopInfo& info)
|
||||
{
|
||||
return MapHas(m_TransitPaths, info);
|
||||
}
|
||||
|
||||
void
|
||||
PathContext::PutPendingRelayCommit(const RouterID& upstream,
|
||||
const PathID_t& txid,
|
||||
const TransitHopInfo& info,
|
||||
const TransitHop& hop)
|
||||
{
|
||||
MapPut(m_WaitingForAcks, PendingPathKey(upstream, txid),
|
||||
std::make_pair(info, hop));
|
||||
}
|
||||
|
||||
bool
|
||||
PathContext::HasPendingRelayCommit(const RouterID& upstream,
|
||||
const PathID_t& txid)
|
||||
{
|
||||
return MapHas(m_WaitingForAcks, PendingPathKey(upstream, txid));
|
||||
}
|
||||
|
||||
TransitHopInfo::TransitHopInfo(const RouterID& down,
|
||||
const LR_CommitRecord& record)
|
||||
: txID(record.txid), upstream(record.nextHop), downstream(down)
|
||||
{
|
||||
}
|
||||
}
|
12
llarp/pathfinder.hpp
Normal file
12
llarp/pathfinder.hpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef LLARP_PATHFINDER_HPP_
|
||||
#define LLARP_PATHFINDER_HPP_
|
||||
#include <llarp/pathfinder.h>
|
||||
|
||||
struct llarp_pathfinder_context {
|
||||
struct llarp_router* router;
|
||||
struct llarp_dht_context* dht;
|
||||
/// copy cstr
|
||||
llarp_pathfinder_context(llarp_router *p_router, struct llarp_dht_context* p_dht);
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue