diff --git a/docs/proto_v0.txt b/docs/proto_v0.txt index 3a50e4acc..b3ff9623c 100644 --- a/docs/proto_v0.txt +++ b/docs/proto_v0.txt @@ -343,6 +343,7 @@ the path is extended by w.y seconds n: "<32 bytes nounce for key exchange>", r: "<16 bytes rx path id>", t: "<16 bytes tx path id>", + u: "", v: 0, w: proof of work } diff --git a/llarp/crypto/encrypted_frame.hpp b/llarp/crypto/encrypted_frame.hpp index 49406191a..b74aaff50 100644 --- a/llarp/crypto/encrypted_frame.hpp +++ b/llarp/crypto/encrypted_frame.hpp @@ -13,7 +13,7 @@ namespace llarp static constexpr size_t EncryptedFrameOverheadSize = PUBKEYSIZE + TUNNONCESIZE + SHORTHASHSIZE; - static constexpr size_t EncryptedFrameBodySize = 512; + static constexpr size_t EncryptedFrameBodySize = 1024; static constexpr size_t EncryptedFrameSize = EncryptedFrameOverheadSize + EncryptedFrameBodySize; diff --git a/llarp/dht/messages/findrouter.cpp b/llarp/dht/messages/findrouter.cpp index 72fc8fc3f..789c80916 100644 --- a/llarp/dht/messages/findrouter.cpp +++ b/llarp/dht/messages/findrouter.cpp @@ -46,7 +46,7 @@ namespace llarp replies.emplace_back(new GotRouterMessage(k, txid, {}, false)); return true; } - // lookup if we don't have it in our nodedb + // lookup if we don't have it in our nodedb dht.LookupRouterForPath(K, txid, pathID, peer); return true; } diff --git a/llarp/exit/session.cpp b/llarp/exit/session.cpp index b2b1f7c1c..b98a4c89d 100644 --- a/llarp/exit/session.cpp +++ b/llarp/exit/session.cpp @@ -82,7 +82,7 @@ namespace llarp } bool - BaseSession::CheckPathDead(path::Path *, llarp_time_t dlt) + BaseSession::CheckPathDead(path::Path*, llarp_time_t dlt) { return dlt >= 10000; } @@ -94,7 +94,9 @@ namespace llarp p->SetDropHandler(std::bind(&BaseSession::HandleTrafficDrop, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - p->SetDeadChecker(std::bind(&BaseSession::CheckPathDead, this, std::placeholders::_1, std::placeholders::_2)); + p->SetDeadChecker(std::bind(&BaseSession::CheckPathDead, this, + std::placeholders::_1, + std::placeholders::_2)); p->SetExitTrafficHandler( std::bind(&BaseSession::HandleTraffic, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); diff --git a/llarp/exit/session.hpp b/llarp/exit/session.hpp index 978f264b1..b70d34bcd 100644 --- a/llarp/exit/session.hpp +++ b/llarp/exit/session.hpp @@ -36,7 +36,7 @@ namespace llarp HandlePathDied(llarp::path::Path* p) override; bool - CheckPathDead(path::Path * p, llarp_time_t dlt); + CheckPathDead(path::Path* p, llarp_time_t dlt); bool SelectHop(llarp_nodedb* db, const RouterContact& prev, RouterContact& cur, diff --git a/llarp/messages/relay_commit.cpp b/llarp/messages/relay_commit.cpp index 308c5d54a..a0b18762a 100644 --- a/llarp/messages/relay_commit.cpp +++ b/llarp/messages/relay_commit.cpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace llarp { @@ -98,6 +99,11 @@ namespace llarp return false; if(!BEncodeWriteDictEntry("t", txid, buf)) return false; + if(nextRC) + { + if(!BEncodeWriteDictEntry("u", *nextRC, buf)) + return false; + } if(!bencode_write_version_entry(buf)) return false; if(work && !BEncodeWriteDictEntry("w", *work, buf)) @@ -129,6 +135,11 @@ namespace llarp return false; if(!BEncodeMaybeReadDictEntry("t", self->txid, read, *key, r->buffer)) return false; + if(*key == "u") + { + self->nextRC = std::make_unique< RouterContact >(); + return self->nextRC->BDecode(r->buffer); + } if(!BEncodeMaybeReadVersion("v", self->version, LLARP_PROTO_VERSION, read, *key, r->buffer)) return false; @@ -199,8 +210,16 @@ namespace llarp static void SendLRCM(void* user) { - std::unique_ptr< LRCMFrameDecrypt > self( + std::shared_ptr< LRCMFrameDecrypt > self( static_cast< LRCMFrameDecrypt* >(user)); + if(!self->context->Router()->ConnectionToRouterAllowed( + 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"); + return; + } // persist sessions to upstream and downstream routers until the commit // ends self->context->Router()->PersistSessionUntil( @@ -209,6 +228,35 @@ namespace llarp self->hop->info.upstream, self->hop->ExpireTime() + 10000); // put hop self->context->PutTransitHop(self->hop); + // if we have an rc for this hop... + if(self->record.nextRC) + { + // ... and it matches the next hop ... + if(self->record.nextHop == self->record.nextRC->pubkey) + { + // ... and it's valid + const auto now = self->context->Router()->Now(); + if(self->record.nextRC->IsPublicRouter() + && self->record.nextRC->Verify(self->context->Crypto(), now)) + { + llarp_nodedb* n = self->context->Router()->nodedb(); + const RouterContact rc = std::move(*self->record.nextRC); + // store it into netdb if we don't have it + if(!n->Has(rc.pubkey)) + { + std::function< void(std::shared_ptr< LRCMFrameDecrypt >) > cb = + [](std::shared_ptr< LRCMFrameDecrypt > ctx) { + ctx->context->ForwardLRCM(ctx->hop->info.upstream, + ctx->frames); + ctx->hop = nullptr; + }; + llarp::Logic* logic = self->context->Router()->logic(); + n->InsertAsync(rc, logic, std::bind(cb, self)); + return; + } + } + } + } // forward to next hop self->context->ForwardLRCM(self->hop->info.upstream, self->frames); self->hop = nullptr; diff --git a/llarp/messages/relay_commit.hpp b/llarp/messages/relay_commit.hpp index 4012b894d..9a270bd60 100644 --- a/llarp/messages/relay_commit.hpp +++ b/llarp/messages/relay_commit.hpp @@ -26,6 +26,7 @@ namespace llarp TunnelNonce tunnelNonce; PathID_t txid, rxid; + std::unique_ptr< RouterContact > nextRC; std::unique_ptr< PoW > work; uint64_t version = 0; uint64_t lifetime = 0; diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index c52707146..c32523a88 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -122,6 +122,8 @@ struct async_insert_rc { llarp_nodedb *nodedb; llarp::RouterContact rc; + llarp::Logic *logic; + std::function< void(void) > completedHook; async_insert_rc(llarp_nodedb *n, const llarp::RouterContact &r) : nodedb(n), rc(r) { @@ -133,13 +135,20 @@ handle_async_insert_rc(void *u) { async_insert_rc *job = static_cast< async_insert_rc * >(u); job->nodedb->Insert(job->rc); + if(job->logic && job->completedHook) + { + job->logic->queue_func(job->completedHook); + } delete job; } void -llarp_nodedb::InsertAsync(llarp::RouterContact rc) +llarp_nodedb::InsertAsync(llarp::RouterContact rc, llarp::Logic *logic, + std::function< void(void) > completionHandler) { async_insert_rc *ctx = new async_insert_rc(this, rc); + ctx->completedHook = completionHandler; + ctx->logic = logic; llarp_threadpool_queue_job(disk, {ctx, &handle_async_insert_rc}); } diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index a188193dd..6b5f80c71 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -79,7 +79,8 @@ struct llarp_nodedb /// insert and write to disk in background void - InsertAsync(llarp::RouterContact rc); + InsertAsync(llarp::RouterContact rc, llarp::Logic *l = nullptr, + std::function< void(void) > completionHandler = nullptr); ssize_t Load(const fs::path &path); diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index fe886bc97..196159725 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -72,6 +72,7 @@ namespace llarp bool isFarthestHop = ctx->idx == ctx->path->hops.size(); + LR_CommitRecord record; if(isFarthestHop) { hop.upstream = hop.rc.pubkey; @@ -79,10 +80,11 @@ namespace llarp else { hop.upstream = ctx->path->hops[ctx->idx].rc.pubkey; + record.nextRC = + std::make_unique< RouterContact >(ctx->path->hops[ctx->idx].rc); } - // build record - LR_CommitRecord record; + record.version = LLARP_PROTO_VERSION; record.txid = hop.txID; record.rxid = hop.rxID; diff --git a/llarp/router/abstractrouter.hpp b/llarp/router/abstractrouter.hpp index c3b50cbbd..ee25a682c 100644 --- a/llarp/router/abstractrouter.hpp +++ b/llarp/router/abstractrouter.hpp @@ -189,6 +189,9 @@ namespace llarp virtual void ForEachPeer(std::function< void(const ILinkSession *, bool) > visit, bool randomize) const = 0; + + virtual bool + ConnectionToRouterAllowed(const RouterID &router) const = 0; }; } // namespace llarp diff --git a/llarp/util/logic.cpp b/llarp/util/logic.cpp index 5e419dbf9..638b06c26 100644 --- a/llarp/util/logic.cpp +++ b/llarp/util/logic.cpp @@ -55,6 +55,12 @@ namespace llarp llarp_timer_run(this->timer, this->thread); } + void + Logic::queue_func(std::function< void(void) > f) + { + this->thread->QueueFunc(f); + } + uint32_t Logic::call_later(const llarp_timeout_job& job) { diff --git a/llarp/util/logic.hpp b/llarp/util/logic.hpp index 534c1da21..1cad6b56c 100644 --- a/llarp/util/logic.hpp +++ b/llarp/util/logic.hpp @@ -43,6 +43,9 @@ namespace llarp void queue_job(struct llarp_thread_job job); + void + queue_func(std::function< void(void) > func); + uint32_t call_later(const llarp_timeout_job& job); diff --git a/llarp/util/threadpool.h b/llarp/util/threadpool.h index 463ef0994..c2e94ff2f 100644 --- a/llarp/util/threadpool.h +++ b/llarp/util/threadpool.h @@ -32,6 +32,18 @@ struct llarp_threadpool absl::ReaderMutexLock l(&m_access); return jobs.size(); } + + void + QueueFunc(std::function< void(void) > f) LOCKS_EXCLUDED(m_access) + { + if(impl) + impl->addJob(f); + else + { + llarp::util::Lock lock(&m_access); + jobs.emplace(f); + } + } }; struct llarp_threadpool *