diff --git a/Makefile b/Makefile index 03973b3e8..a35686bb9 100644 --- a/Makefile +++ b/Makefile @@ -82,7 +82,7 @@ testnet-clean: clean rm -rf $(TESTNET_ROOT) testnet-configure: testnet-clean - cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX) -DTUNTAP=ON + cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX) -DTUNTAP=ON testnet-build: testnet-configure ninja diff --git a/include/llarp/aligned.hpp b/include/llarp/aligned.hpp index b30d129da..5b28513f6 100644 --- a/include/llarp/aligned.hpp +++ b/include/llarp/aligned.hpp @@ -21,12 +21,8 @@ namespace llarp { if(randomize) Randomize(); - } - - AlignedBuffer(const AlignedBuffer& other) - { - for(size_t idx = 0; idx < (sz / 8); ++idx) - l[idx] = other.l[idx]; + else + Zero(); } AlignedBuffer(const byte_t* data) @@ -68,6 +64,24 @@ namespace llarp return memcmp(l, other.l, sz) < 0; } + bool + operator>(const AlignedBuffer& other) const + { + return memcmp(l, other.l, sz) > 0; + } + + bool + operator<=(const AlignedBuffer& other) const + { + return memcmp(l, other.l, sz) <= 0; + } + + bool + operator>=(const AlignedBuffer& other) const + { + return memcmp(l, other.l, sz) >= 0; + } + AlignedBuffer operator^(const AlignedBuffer& other) const { @@ -110,7 +124,7 @@ namespace llarp size_t idx = sz / 8; while(idx) { - if(l[idx--]) + if(l[--idx]) return false; } return true; diff --git a/include/llarp/bencode.hpp b/include/llarp/bencode.hpp index 99de73346..3d666d84a 100644 --- a/include/llarp/bencode.hpp +++ b/include/llarp/bencode.hpp @@ -14,12 +14,13 @@ namespace llarp return bencode_write_bytestring(buf, k, 1) && bencode_write_bytestring(buf, t, 1); } + template < typename Obj_t > bool BEncodeWriteDictString(const char* k, const Obj_t& str, llarp_buffer_t* buf) { return bencode_write_bytestring(buf, k, 1) - && bencode_write_bytestring(buf, str.c_str(), str.size()); + && bencode_write_bytestring(buf, str.data(), str.size()); } template < typename Obj_t > @@ -149,11 +150,7 @@ namespace llarp T item; if(!item.BDecode(buf)) return false; - result.insert(item); - /* - if(!result.insert(item).second) - return false; - */ + return result.insert(item).second; } if(*buf->cur != 'e') // make sure we're at a list end return false; diff --git a/include/llarp/dht/bucket.hpp b/include/llarp/dht/bucket.hpp index e9acacf41..a086da099 100644 --- a/include/llarp/dht/bucket.hpp +++ b/include/llarp/dht/bucket.hpp @@ -19,8 +19,7 @@ namespace llarp Bucket(const Key_t& us) : nodes(XorMetric(us)){}; bool - GetRandomNodeExcluding(Key_t& result, - const std::set< Key_t >& exclude) const + GetRandomNodeExcluding(Key_t& result, std::set< Key_t > exclude) const { std::vector< Key_t > candidates; for(const auto& item : nodes) @@ -53,7 +52,7 @@ namespace llarp bool FindCloseExcluding(const Key_t& target, Key_t& result, - const std::set< Key_t >& exclude) const + std::set< Key_t > exclude) const { Key_t maxdist; maxdist.Fill(0xff); @@ -61,8 +60,9 @@ namespace llarp mindist.Fill(0xff); for(const auto& item : nodes) { - if(exclude.find(item.first) != exclude.end()) + if(exclude.count(item.first)) continue; + auto curDist = item.first ^ target; if(curDist < mindist) { diff --git a/include/llarp/dht/context.hpp b/include/llarp/dht/context.hpp index 0283dc12c..092f21fa1 100644 --- a/include/llarp/dht/context.hpp +++ b/include/llarp/dht/context.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -60,7 +61,43 @@ namespace llarp void LookupIntroSetForPath(const service::Address& addr, uint64_t txid, - const llarp::PathID_t& path, const Key_t& askpeer); + const llarp::PathID_t& path, Key_t askpeer); + + template < typename Job, typename Result > + void + TryLookupAgain(Job* j, Result r, uint64_t R) + { + const Key_t targetKey = j->target.ToKey(); + Key_t askpeer; + std::set< Key_t > exclude = j->asked; + if(!nodes->FindCloseExcluding(targetKey, askpeer, exclude)) + { + j->Exausted(); + delete j; + return; + } + if((OurKey() ^ targetKey) < (askpeer ^ targetKey)) + { + j->Exausted(); + delete j; + return; + } + auto id = ++ids; + TXOwner ownerKey; + ownerKey.node = askpeer; + ownerKey.txid = id; + SearchJob job(j->whoasked, j->txid, r, [j]() { delete j; }); + pendingTX[ownerKey] = job; + auto msg = new FindIntroMessage(id, j->target); + msg->R = R; + llarp::LogInfo("asking ", askpeer, " for ", j->target.ToString(), + " with txid=", id); + DHTSendTo(askpeer, msg); + j->asked.insert(std::move(askpeer)); + } + + void + DHTSendTo(const Key_t& peer, IMessage* msg); void LookupIntroSetRelayed(const Key_t& requester, uint64_t txid, diff --git a/include/llarp/dht/messages/findintro.hpp b/include/llarp/dht/messages/findintro.hpp index 152f644f3..4287f62ce 100644 --- a/include/llarp/dht/messages/findintro.hpp +++ b/include/llarp/dht/messages/findintro.hpp @@ -21,16 +21,14 @@ namespace llarp relayed = relay; } - FindIntroMessage(const Key_t& from, const llarp::service::Tag& tag, - uint64_t txid) - : IMessage(from), N(tag), T(txid) + FindIntroMessage(const llarp::service::Tag& tag, uint64_t txid) + : IMessage({}), N(tag), T(txid) { S.Zero(); } - FindIntroMessage(const Key_t& from, const llarp::service::Address& addr, - uint64_t txid) - : IMessage(from), S(addr), T(txid) + FindIntroMessage(uint64_t txid, const llarp::service::Address& addr) + : IMessage({}), S(addr), T(txid) { N.Zero(); } diff --git a/include/llarp/dht/messages/gotrouter.hpp b/include/llarp/dht/messages/gotrouter.hpp index 61369a497..cd6b3d7ef 100644 --- a/include/llarp/dht/messages/gotrouter.hpp +++ b/include/llarp/dht/messages/gotrouter.hpp @@ -8,11 +8,13 @@ namespace llarp { struct GotRouterMessage : public IMessage { - GotRouterMessage(const Key_t& from) : IMessage(from) + GotRouterMessage(const Key_t& from, bool tunneled) + : IMessage(from), relayed(tunneled) { } - GotRouterMessage(const Key_t& from, uint64_t id, const llarp_rc* result) - : IMessage(from), txid(id) + GotRouterMessage(const Key_t& from, uint64_t id, const llarp_rc* result, + bool tunneled) + : IMessage(from), txid(id), relayed(tunneled) { if(result) { @@ -37,6 +39,7 @@ namespace llarp std::vector< llarp_rc > R; uint64_t txid = 0; uint64_t version = 0; + bool relayed = false; }; } // namespace dht } // namespace llarp diff --git a/include/llarp/dht/search_job.hpp b/include/llarp/dht/search_job.hpp index 19091ff1c..a71cf78fb 100644 --- a/include/llarp/dht/search_job.hpp +++ b/include/llarp/dht/search_job.hpp @@ -18,9 +18,11 @@ namespace llarp { const static uint64_t JobTimeout = 30000; - typedef std::function< void( + typedef std::function< bool( const std::vector< llarp::service::IntroSet >&) > IntroSetHookFunc; + + typedef std::function< void(void) > DoneFunc; SearchJob(); /// for routers SearchJob(const Key_t& requester, uint64_t requesterTX, @@ -29,15 +31,15 @@ namespace llarp /// for introsets SearchJob(const Key_t& requester, uint64_t requesterTX, const Key_t& target, const std::set< Key_t >& excludes, - IntroSetHookFunc found); + IntroSetHookFunc found, DoneFunc done); // for introsets via tag SearchJob(const Key_t& requester, uint64_t requseterTX, - IntroSetHookFunc found); + IntroSetHookFunc found, DoneFunc done); void FoundRouter(const llarp_rc* router) const; - void + bool FoundIntros( const std::vector< llarp::service::IntroSet >& introset) const; @@ -50,6 +52,7 @@ namespace llarp // only set if looking up router llarp_router_lookup_job* job = nullptr; IntroSetHookFunc foundIntroHook; + DoneFunc onDone; llarp_time_t started; Key_t requester; uint64_t requesterTX; diff --git a/include/llarp/iwp.h b/include/llarp/iwp.hpp similarity index 69% rename from include/llarp/iwp.h rename to include/llarp/iwp.hpp index e05968340..a8482864c 100644 --- a/include/llarp/iwp.h +++ b/include/llarp/iwp.hpp @@ -1,7 +1,7 @@ -#ifndef LLARP_IWP_H_ -#define LLARP_IWP_H_ +#ifndef LLARP_IWP_HPP +#define LLARP_IWP_HPP #include -#include "router.hpp" +#include struct llarp_iwp_args { @@ -9,7 +9,7 @@ struct llarp_iwp_args struct llarp_logic* logic; struct llarp_threadpool* cryptoworker; struct llarp_router* router; - const char* keyfile; + std::string keyfile; }; #endif diff --git a/include/llarp/iwp/server.hpp b/include/llarp/iwp/server.hpp index 7ab59b828..6f23d58df 100644 --- a/include/llarp/iwp/server.hpp +++ b/include/llarp/iwp/server.hpp @@ -1,5 +1,5 @@ #pragma once -#include +#include #include #include "llarp/iwp/establish_job.hpp" #include "router.hpp" @@ -26,7 +26,7 @@ struct llarp_link llarp_link *parent = nullptr; llarp_udp_io udp; llarp::Addr addr; - char keyfile[255]; + std::string keyfile; uint32_t timeout_job_id; const char * diff --git a/include/llarp/path.hpp b/include/llarp/path.hpp index 564825627..8aee1dbe0 100644 --- a/include/llarp/path.hpp +++ b/include/llarp/path.hpp @@ -358,6 +358,9 @@ namespace llarp PathSet* GetLocalPathSet(const PathID_t& id); + routing::IMessageHandler* + GetHandler(const PathID_t& id); + bool ForwardLRCM(const RouterID& nextHop, std::deque< EncryptedFrame >& frames); diff --git a/include/llarp/pathset.hpp b/include/llarp/pathset.hpp index 6fffc7f6c..8b0f15d6b 100644 --- a/include/llarp/pathset.hpp +++ b/include/llarp/pathset.hpp @@ -78,6 +78,19 @@ namespace llarp return false; } + /// override me in subtype + virtual bool + HandleGotRouterMessage(const llarp::dht::GotRouterMessage* msg) + { + return false; + } + + virtual routing::IMessageHandler* + GetDHTHandler() + { + return nullptr; + } + Path* GetEstablishedPathClosestTo(const RouterID& router) const; @@ -87,6 +100,9 @@ namespace llarp Path* GetPathByRouter(const RouterID& router) const; + Path* + GetPathByID(const PathID_t& id) const; + bool GetCurrentIntroductions( std::set< llarp::service::Introduction >& intros) const; diff --git a/include/llarp/pow.hpp b/include/llarp/pow.hpp index d9cd6ae93..bf2c93026 100644 --- a/include/llarp/pow.hpp +++ b/include/llarp/pow.hpp @@ -19,9 +19,6 @@ namespace llarp bool IsValid(llarp_shorthash_func hashfunc) const; - bool - BDecode(llarp_buffer_t* buf); - bool DecodeKey(llarp_buffer_t k, llarp_buffer_t* val); diff --git a/include/llarp/service/Info.hpp b/include/llarp/service/Info.hpp index b54363a74..6bcbab60a 100644 --- a/include/llarp/service/Info.hpp +++ b/include/llarp/service/Info.hpp @@ -10,14 +10,58 @@ namespace llarp { struct ServiceInfo : public llarp::IBEncodeMessage { + private: llarp::PubKey enckey; llarp::PubKey signkey; - uint64_t version = 0; VanityNonce vanity; - ServiceInfo(); + public: + ServiceInfo() = default; + + ServiceInfo(const ServiceInfo&& other) + { + enckey = std::move(other.enckey); + signkey = std::move(other.signkey); + version = std::move(other.version); + vanity = std::move(other.vanity); + m_CachedAddr = std::move(other.m_CachedAddr); + } + + ServiceInfo(const ServiceInfo& other) + { + enckey = other.enckey; + signkey = other.signkey; + version = other.version; + vanity = other.vanity; + m_CachedAddr = other.m_CachedAddr; + } + + void + RandomizeVanity() + { + vanity.Randomize(); + } + + bool + Verify(llarp_crypto* crypto, llarp_buffer_t payload, + const Signature& sig) const + { + return crypto->verify(signkey, payload, sig); + } + + byte_t* + EncryptionPublicKey() + { + return enckey; + } - ~ServiceInfo(); + bool + Update(const byte_t* enc, const byte_t* sign) + { + enckey = enc; + signkey = sign; + return UpdateAddr(); + } bool operator==(const ServiceInfo& other) const @@ -26,6 +70,12 @@ namespace llarp && version == other.version && vanity == other.vanity; } + bool + operator!=(const ServiceInfo& other) const + { + return !(*this == other); + } + ServiceInfo& operator=(const ServiceInfo& other) { @@ -50,7 +100,7 @@ namespace llarp << " v=" << i.version << " x=" << i.vanity << "]"; } - /// compute .loki address + /// .loki address std::string Name() const; @@ -70,9 +120,9 @@ namespace llarp bool BDecode(llarp_buffer_t* buf) { - if(!IBEncodeMessage::BDecode(buf)) - return false; - return CalculateAddress(m_CachedAddr); + if(IBEncodeMessage::BDecode(buf)) + return CalculateAddress(m_CachedAddr.data()); + return false; } bool diff --git a/include/llarp/service/IntroSet.hpp b/include/llarp/service/IntroSet.hpp index 17fe1a10d..1f3abd72e 100644 --- a/include/llarp/service/IntroSet.hpp +++ b/include/llarp/service/IntroSet.hpp @@ -25,6 +25,29 @@ namespace llarp llarp::PoW* W = nullptr; llarp::Signature Z; + IntroSet() = default; + + IntroSet(const IntroSet&& other) + { + A = std::move(other.A); + I = std::move(other.I); + version = std::move(other.version); + topic = std::move(other.topic); + W = std::move(other.W); + Z = std::move(other.Z); + } + + IntroSet(const IntroSet& other) + { + A = other.A; + I = other.I; + version = other.version; + topic = other.topic; + if(other.W) + W = new llarp::PoW(*other.W); + Z = other.Z; + } + ~IntroSet(); IntroSet& @@ -73,6 +96,23 @@ namespace llarp return out << " V=" << i.version << " Z=" << i.Z; } + bool + IsNewerThan(const IntroSet& other) const + { + return GetNewestIntro().expiresAt > other.GetNewestIntro().expiresAt; + } + + Introduction + GetNewestIntro() const + { + Introduction i; + i.expiresAt = 0; + for(const auto& intro : I) + if(intro.expiresAt > i.expiresAt) + i = intro; + return i; + } + bool HasExpiredIntros(llarp_time_t now) const; diff --git a/include/llarp/service/address.hpp b/include/llarp/service/address.hpp index 0f8c923dc..65971555e 100644 --- a/include/llarp/service/address.hpp +++ b/include/llarp/service/address.hpp @@ -2,13 +2,14 @@ #define LLARP_SERVICE_ADDRESS_HPP #include #include +#include #include namespace llarp { namespace service { - struct Address : public llarp::AlignedBuffer< 32 > + struct Address { std::string ToString() const; @@ -16,28 +17,152 @@ namespace llarp bool FromString(const std::string& str); - Address() : llarp::AlignedBuffer< 32 >() + Address() { + Zero(); } - Address(const byte_t* data) : llarp::AlignedBuffer< 32 >(data) + Address(const Address& other) { + memcpy(b, other.b, 32); } - struct Hash + + byte_t& operator[](size_t idx) { - size_t - operator()(const Address& addr) const + return b[idx]; + } + + const byte_t& operator[](size_t idx) const + { + return b[idx]; + } + + bool + BEncode(llarp_buffer_t* buf) const + { + return bencode_write_bytestring(buf, b, 32); + } + + bool + BDecode(llarp_buffer_t* buf) + { + llarp_buffer_t strbuf; + if(!bencode_read_string(buf, &strbuf)) + return false; + if(strbuf.sz != 32) { - size_t idx = 0; - memcpy(&idx, addr, sizeof(idx)); - return idx; + llarp::LogErrorTag("Address::BDecode", + "bdecode buffer size missmatch ", strbuf.sz, + "!=32"); + return false; } - }; + memcpy(b, strbuf.base, 32); + return true; + } - operator const dht::Key_t() const + size_t + size() const + { + return 32; + } + + bool + IsZero() const + { + size_t sz = 4; + while(sz) + { + if(l[--sz]) + return false; + } + return true; + } + + void + Zero() + { + size_t sz = 4; + while(sz) + { + l[--sz] = 0; + } + } + + bool + operator<(const Address& other) const + { + return memcmp(data(), other.data(), 32) < 0; + } + + friend std::ostream& + operator<<(std::ostream& out, const Address& self) + { + return out << self.ToString(); + } + + bool + operator==(const Address& other) const + { + return memcmp(data(), other.data(), 32) == 0; + } + + bool + operator!=(const Address& other) const + { + return !(*this == other); + } + + Address& + operator=(const Address& other) + { + memcpy(data(), other.data(), 32); + return *this; + } + + const dht::Key_t + ToKey() const { return dht::Key_t(data()); } + + const RouterID + ToRouter() const + { + return RouterID(data()); + } + + const byte_t* + data() const + { + return b; + } + + byte_t* + data() + { + return b; + } + + const uint64_t* + data_l() const + { + return l; + } + + struct Hash + { + size_t + operator()(const Address& buf) const + { + return *buf.data_l(); + } + }; + + private: + union { + byte_t b[32]; + uint64_t l[4]; + }; }; } // namespace service diff --git a/include/llarp/service/endpoint.hpp b/include/llarp/service/endpoint.hpp index c3dd34d1a..2303778b2 100644 --- a/include/llarp/service/endpoint.hpp +++ b/include/llarp/service/endpoint.hpp @@ -67,6 +67,9 @@ namespace llarp bool HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg); + bool + HandleGotRouterMessage(const llarp::dht::GotRouterMessage* msg); + bool HandleHiddenServiceFrame(const llarp::service::ProtocolFrame* msg); @@ -90,6 +93,10 @@ namespace llarp // override me in subclass } + /// ensure that we know a router, looks up if it doesn't + void + EnsureRouterIsKnown(const RouterID& router); + Identity* GetIdentity() { @@ -136,9 +143,6 @@ namespace llarp bool SelectHop(llarp_nodedb* db, llarp_rc* prev, llarp_rc* cur, size_t hop); - bool - HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg); - bool HandleHiddenServiceFrame(const ProtocolFrame* frame); @@ -149,6 +153,9 @@ namespace llarp Name() const; private: + bool + OnIntroSetUpdate(const IntroSet* i); + void EncryptAndSendTo(llarp_buffer_t payload); @@ -227,6 +234,9 @@ namespace llarp IsolateNetwork(); private: + bool + OnOutboundLookup(const IntroSet* i); /* */ + static bool SetupIsolatedNetwork(void* user); @@ -252,6 +262,9 @@ namespace llarp m_RemoteSessions; std::unordered_map< Address, PathEnsureHook, Address::Hash > m_PendingServiceLookups; + + std::unordered_map< RouterID, uint64_t, RouterID::Hash > m_PendingRouters; + uint64_t m_CurrentPublishTX = 0; llarp_time_t m_LastPublish = 0; llarp_time_t m_LastPublishAttempt = 0; diff --git a/include/llarp/service/protocol.hpp b/include/llarp/service/protocol.hpp index cf61f14a6..e5b2c3e2e 100644 --- a/include/llarp/service/protocol.hpp +++ b/include/llarp/service/protocol.hpp @@ -82,7 +82,7 @@ namespace llarp BEncode(llarp_buffer_t* buf) const; bool - Verify(llarp_crypto* c, byte_t* signingkey) const; + Verify(llarp_crypto* c, const ServiceInfo& from) const; bool HandleMessage(llarp::routing::IMessageHandler* h, llarp_router* r) const; diff --git a/include/llarp/service/tag.hpp b/include/llarp/service/tag.hpp index 7aad93edd..559f543a6 100644 --- a/include/llarp/service/tag.hpp +++ b/include/llarp/service/tag.hpp @@ -13,7 +13,6 @@ namespace llarp { Tag() : llarp::AlignedBuffer< 16 >() { - Zero(); } Tag(const byte_t* d) : llarp::AlignedBuffer< 16 >(d) @@ -36,17 +35,26 @@ namespace llarp return *this; } - llarp::dht::Key_t - Key() const + Tag& + operator=(const std::string& str) { - llarp::dht::Key_t k; - crypto_generichash(k, 32, data(), 16, nullptr, 0); - return k; +#ifndef MIN +#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) + memcpy(data(), str.data(), MIN(16UL, str.size())); +#undef MIN +#endif + return *this; } std::string ToString() const; + bool + Empty() const + { + return ToString().empty(); + } + struct Hash { std::size_t diff --git a/llarp/dht/context.cpp b/llarp/dht/context.cpp index fa30c2e08..ce857873c 100644 --- a/llarp/dht/context.cpp +++ b/llarp/dht/context.cpp @@ -51,18 +51,52 @@ namespace llarp struct PathLookupJob { + Key_t whoasked; + service::Address target; uint64_t txid; PathID_t pathID; llarp_router *m_router; std::set< service::IntroSet > localIntroSets; std::set< Key_t > asked; + int m_TriesLeft = 5; + uint64_t R = 0; PathLookupJob(llarp_router *r, const PathID_t &localpath, uint64_t tx) : txid(tx), pathID(localpath), m_router(r) { + whoasked = r->dht->impl.OurKey(); } void + TryAgain() + { + --m_TriesLeft; + auto &dht = m_router->dht->impl; + llarp::LogInfo("try lookup again"); + dht.TryLookupAgain( + this, + std::bind(&PathLookupJob::OnResult, this, std::placeholders::_1), + R); + } + + void + Exausted() + { + llarp::LogWarn("Exausted peers for lookup"); + auto path = + m_router->paths.GetByUpstream(m_router->dht->impl.OurKey(), pathID); + if(path) + { + llarp::routing::DHTMessage msg; + msg.M.push_back(new llarp::dht::GotIntroMessage( + std::vector< service::IntroSet >(), txid)); + path->SendRoutingMessage(&msg, m_router); + } + else + llarp::LogError("no path for lookup pathid=", pathID); + } + + bool OnResult(const std::vector< service::IntroSet > &results) { auto path = @@ -73,23 +107,35 @@ namespace llarp { localIntroSets.insert(introset); } - llarp::routing::DHTMessage msg; auto sz = localIntroSets.size(); - std::vector< service::IntroSet > intros(sz); - for(const auto &i : localIntroSets) + if(sz || target.IsZero() || m_TriesLeft == 0) { - intros[--sz] = i; + llarp::routing::DHTMessage msg; + + std::vector< service::IntroSet > intros(sz); + for(const auto &i : localIntroSets) + { + intros[--sz] = i; + } + llarp::LogInfo("found ", sz, " introsets for txid=", txid); + msg.M.push_back(new llarp::dht::GotIntroMessage(intros, txid)); + path->SendRoutingMessage(&msg, m_router); + } + else if(!target.IsZero()) + { + if(m_TriesLeft) + { + TryAgain(); + return false; + } } - llarp::LogInfo("found ", sz, " introsets for txid=", txid); - msg.M.push_back(new llarp::dht::GotIntroMessage(intros, txid)); - path->SendRoutingMessage(&msg, m_router); } else { llarp::LogWarn("no local path for reply on PathTagLookupJob pathid=", pathID); } - delete this; + return true; } }; @@ -110,8 +156,10 @@ namespace llarp TXOwner ownerKey; ownerKey.node = peer; ownerKey.txid = id; - SearchJob job(from, txid, - [](const std::vector< service::IntroSet > &) {}); + SearchJob job( + from, txid, + [](const std::vector< service::IntroSet > &) -> bool { return true; }, + []() {}); pendingTX[ownerKey] = job; auto msg = new llarp::DHTImmeidateMessage(peer); msg->msgs.push_back(new PublishIntroMessage(introset, id, S, E)); @@ -130,12 +178,14 @@ namespace llarp j->localIntroSets = FindRandomIntroSetsWithTag(tag); SearchJob job( OurKey(), txid, - std::bind(&PathLookupJob::OnResult, j, std::placeholders::_1)); + std::bind(&PathLookupJob::OnResult, j, std::placeholders::_1), + [j]() { delete j; }); pendingTX[ownerKey] = job; auto msg = new llarp::DHTImmeidateMessage(askpeer); - auto dhtmsg = new FindIntroMessage({}, tag, id); + auto dhtmsg = new FindIntroMessage(tag, id); dhtmsg->R = 5; + j->R = 5; msg->msgs.push_back(dhtmsg); llarp::LogInfo("asking ", askpeer, " for tag ", tag.ToString(), " with ", j->localIntroSets.size(), " local tags txid=", txid); @@ -144,24 +194,29 @@ namespace llarp void Context::LookupIntroSetForPath(const service::Address &addr, uint64_t txid, - const llarp::PathID_t &path, - const Key_t &askpeer) + const llarp::PathID_t &path, Key_t askpeer) { auto id = ++ids; TXOwner ownerKey; ownerKey.node = askpeer; ownerKey.txid = id; PathLookupJob *j = new PathLookupJob(router, path, txid); + j->target = addr; + j->R = 5; + j->asked.emplace(askpeer); + Key_t us = OurKey(); + j->asked.emplace(us); SearchJob job( OurKey(), txid, - std::bind(&PathLookupJob::OnResult, j, std::placeholders::_1)); + std::bind(&PathLookupJob::OnResult, j, std::placeholders::_1), + [j]() { delete j; }); pendingTX[ownerKey] = job; auto msg = new llarp::DHTImmeidateMessage(askpeer); - auto dhtmsg = new FindIntroMessage(addr, id); + auto dhtmsg = new FindIntroMessage(id, addr); dhtmsg->R = 5; msg->msgs.push_back(dhtmsg); - llarp::LogInfo("askng ", askpeer, " for ", addr.ToString(), + llarp::LogInfo("asking ", askpeer, " for ", addr.ToString(), " with txid=", id); router->SendToOrQueue(askpeer, msg); } @@ -213,7 +268,8 @@ namespace llarp if(target == ourKey) { // we are the target, give them our RC - replies.push_back(new GotRouterMessage(requester, txid, &router->rc)); + replies.push_back( + new GotRouterMessage(requester, txid, &router->rc, false)); return; } Key_t next; @@ -223,8 +279,8 @@ namespace llarp if(next == target) { // we know it - replies.push_back( - new GotRouterMessage(requester, txid, nodes->nodes[target].rc)); + replies.push_back(new GotRouterMessage( + requester, txid, nodes->nodes[target].rc, false)); } else if(recursive) // are we doing a recursive lookup? { @@ -234,7 +290,8 @@ namespace llarp // so we won't ask neighboor recursively, tell them we don't have it llarp::LogInfo("we aren't closer to ", target, " than ", next, " so we end it here"); - replies.push_back(new GotRouterMessage(requester, txid, nullptr)); + replies.push_back( + new GotRouterMessage(requester, txid, nullptr, false)); } else { @@ -250,7 +307,8 @@ namespace llarp llarp::LogInfo("we don't have ", target, " and this was an iterative request so telling ", requester, " that we don't have it"); - replies.push_back(new GotRouterMessage(requester, txid, nullptr)); + replies.push_back( + new GotRouterMessage(requester, txid, nullptr, false)); } } else @@ -259,7 +317,8 @@ namespace llarp llarp::LogInfo("we don't have ", target, " and have no closer peers so telling ", requester, " that we don't have it"); - replies.push_back(new GotRouterMessage(requester, txid, nullptr)); + replies.push_back( + new GotRouterMessage(requester, txid, nullptr, false)); } } @@ -334,6 +393,14 @@ namespace llarp {1000, this, &handle_cleaner_timer}); } + void + Context::DHTSendTo(const Key_t &peer, IMessage *msg) + { + auto m = new llarp::DHTImmeidateMessage(peer); + m->msgs.push_back(msg); + router->SendToOrQueue(peer, m); + } + bool Context::RelayRequestForPath(const llarp::PathID_t &id, const IMessage *msg) { @@ -351,34 +418,75 @@ namespace llarp /// handles replying with a GIM for a lookup struct IntroSetInformJob { + service::Address target; + uint64_t R = 0; + int m_TriesLeft = 5; std::set< service::IntroSet > localIntroSets; - Key_t replyNode; + std::set< Key_t > asked; + Key_t whoasked; uint64_t txid; llarp_router *m_Router; IntroSetInformJob(llarp_router *r, const Key_t &replyTo, uint64_t id) - : replyNode(replyTo), txid(id), m_Router(r) + : whoasked(replyTo), txid(id), m_Router(r) { } void + Exausted() + { + auto msg = new llarp::DHTImmeidateMessage(whoasked); + msg->msgs.push_back(new GotIntroMessage({}, txid)); + m_Router->SendToOrQueue(whoasked, msg); + } + + void + TryAgain() + { + --m_TriesLeft; + llarp::LogInfo("try lookup again"); + auto &dht = m_Router->dht->impl; + dht.TryLookupAgain(this, + std::bind(&IntroSetInformJob::OnResult, this, + std::placeholders::_1), + R); + } + + bool OnResult(const std::vector< llarp::service::IntroSet > &results) { for(const auto &introset : results) { - localIntroSets.insert(introset); + localIntroSets.insert(std::move(introset)); } - if(replyNode != m_Router->dht->impl.OurKey()) + if(whoasked != m_Router->dht->impl.OurKey()) { - std::vector< service::IntroSet > reply; - for(const auto &introset : localIntroSets) + size_t sz = localIntroSets.size(); + if(sz || target.IsZero() || m_TriesLeft == 0) { - reply.push_back(introset); + std::vector< service::IntroSet > reply; + for(const auto &introset : localIntroSets) + { + reply.push_back(std::move(introset)); + } + localIntroSets.clear(); + auto msg = new llarp::DHTImmeidateMessage(whoasked); + msg->msgs.push_back(new GotIntroMessage(reply, txid)); + m_Router->SendToOrQueue(whoasked, msg); } - auto msg = new llarp::DHTImmeidateMessage(replyNode); - msg->msgs.push_back(new GotIntroMessage(reply, txid)); - m_Router->SendToOrQueue(replyNode, msg); + else if(!target.IsZero()) + { + if(m_TriesLeft) + { + TryAgain(); + return false; + } + } + } + else + { + llarp::LogWarn("we asked for something without a path?"); } - delete this; + return true; } }; @@ -397,11 +505,12 @@ namespace llarp j->localIntroSets = include; SearchJob job( whoasked, txid, - std::bind(&IntroSetInformJob::OnResult, j, std::placeholders::_1)); + std::bind(&IntroSetInformJob::OnResult, j, std::placeholders::_1), + [j]() { delete j; }); pendingTX[ownerKey] = job; auto msg = new llarp::DHTImmeidateMessage(askpeer); - auto dhtmsg = new FindIntroMessage({}, tag, id); + auto dhtmsg = new FindIntroMessage(tag, id); dhtmsg->R = R; msg->msgs.push_back(dhtmsg); router->SendToOrQueue(askpeer, msg); @@ -420,15 +529,22 @@ namespace llarp ownerKey.node = askpeer; ownerKey.txid = id; IntroSetInformJob *j = new IntroSetInformJob(router, whoasked, txid); + j->target = addr; + for(const auto &item : excludes) + j->asked.emplace(item); + j->R = R; SearchJob job( - whoasked, txid, addr, excludes, - std::bind(&IntroSetInformJob::OnResult, j, std::placeholders::_1)); + whoasked, txid, addr.ToKey(), {}, + std::bind(&IntroSetInformJob::OnResult, j, std::placeholders::_1), + [j]() { delete j; }); pendingTX[ownerKey] = job; auto msg = new llarp::DHTImmeidateMessage(askpeer); - auto dhtmsg = new FindIntroMessage({}, addr, id); + auto dhtmsg = new FindIntroMessage(id, addr); dhtmsg->R = R; msg->msgs.push_back(dhtmsg); + llarp::LogInfo("asking ", askpeer, " for ", addr.ToString(), + " on request of ", whoasked); router->SendToOrQueue(askpeer, msg); } diff --git a/llarp/dht/decode.cpp b/llarp/dht/decode.cpp index fa06d7c61..994d23948 100644 --- a/llarp/dht/decode.cpp +++ b/llarp/dht/decode.cpp @@ -49,15 +49,7 @@ namespace llarp dec->msg = new FindRouterMessage(dec->From); break; case 'S': - if(dec->relayed) - { - llarp::LogWarn( - "GotRouterMessage found when parsing relayed DHT " - "message"); - return false; - } - else - dec->msg = new GotRouterMessage(dec->From); + dec->msg = new GotRouterMessage(dec->From, dec->relayed); break; case 'I': dec->msg = new PublishIntroMessage(); diff --git a/llarp/dht/find_intro.cpp b/llarp/dht/find_intro.cpp index 436db104b..dac54ed57 100644 --- a/llarp/dht/find_intro.cpp +++ b/llarp/dht/find_intro.cpp @@ -57,9 +57,8 @@ namespace llarp // message id if(!BEncodeWriteDictMsgType(buf, "A", "F")) return false; - if(N.IsZero()) + if(N.Empty()) { - return false; // r5n counter if(!BEncodeWriteDictInt("R", R, buf)) return false; @@ -103,8 +102,9 @@ namespace llarp } Key_t peer; std::set< Key_t > exclude = {dht.OurKey(), From}; - if(N.ToString().empty()) + if(N.Empty()) { + llarp::LogInfo("lookup ", S.ToString()); const auto introset = dht.GetIntroSetByServiceAddress(S); if(introset) { @@ -114,22 +114,34 @@ namespace llarp } else { - if(R == 0 && !relayed) + if(R == 0) { - // we are iterative and don't have it, reply with a direct reply + // we don't have it, reply with a direct reply + llarp::LogInfo("dont have intro set and no recursion"); replies.push_back(new GotIntroMessage({}, T)); } else { + const auto& us = dht.OurKey(); + auto target = S.ToKey(); // we are recursive - if(dht.nodes->FindCloseExcluding(S, peer, exclude)) + if(dht.nodes->FindCloseExcluding(target, peer, exclude)) { if(relayed) dht.LookupIntroSetForPath(S, T, pathID, peer); - else if(R >= 1) - dht.LookupIntroSet(S, From, T, peer, R - 1); else - dht.LookupIntroSet(S, From, T, peer, 0); + { + if((us ^ target) < (peer ^ target)) + { + // we are not closer than our peer to the target so don't + // revurse + replies.push_back(new GotIntroMessage({}, T)); + } + else if(R >= 1) + dht.LookupIntroSet(S, From, T, peer, R - 1, exclude); + else + dht.LookupIntroSet(S, From, T, peer, 0, exclude); + } } else { diff --git a/llarp/dht/find_router.cpp b/llarp/dht/find_router.cpp index ac345e1a0..97a67f450 100644 --- a/llarp/dht/find_router.cpp +++ b/llarp/dht/find_router.cpp @@ -45,8 +45,8 @@ namespace llarp { if(llarp_rc_verify_sig(&self->router->crypto, &job->result)) { - reply.M.push_back( - new GotRouterMessage(job->target, self->txid, &job->result)); + reply.M.push_back(new GotRouterMessage(job->target, self->txid, + &job->result, false)); } llarp_rc_free(&job->result); llarp_rc_clear(&job->result); @@ -54,7 +54,7 @@ namespace llarp else { reply.M.push_back( - new GotRouterMessage(job->target, self->txid, nullptr)); + new GotRouterMessage(job->target, self->txid, nullptr, false)); } self->SendReply(&reply); // TODO: is this okay? @@ -74,7 +74,8 @@ namespace llarp auto path = dht.router->paths.GetByUpstream(K, pathID); if(path) { - replies.push_back(new GotRouterMessage(K, txid, &dht.router->rc)); + replies.push_back( + new GotRouterMessage(K, txid, &dht.router->rc, false)); return true; } return false; diff --git a/llarp/dht/got_intro.cpp b/llarp/dht/got_intro.cpp index 10548c545..84839c747 100644 --- a/llarp/dht/got_intro.cpp +++ b/llarp/dht/got_intro.cpp @@ -39,8 +39,11 @@ namespace llarp auto pending = dht.FindPendingTX(From, T); if(pending) { - pending->FoundIntros(I); - dht.RemovePendingLookup(From, T); + if(pending->FoundIntros(I)) + { + dht.RemovePendingLookup(From, T); + llarp::LogInfo("removed pending tx from ", From, " txid=", T); + } return true; } else diff --git a/llarp/dht/got_router.cpp b/llarp/dht/got_router.cpp index 88b7f960e..377980649 100644 --- a/llarp/dht/got_router.cpp +++ b/llarp/dht/got_router.cpp @@ -61,7 +61,15 @@ namespace llarp GotRouterMessage::HandleMessage(llarp_dht_context *ctx, std::vector< IMessage * > &replies) const { - auto &dht = ctx->impl; + auto &dht = ctx->impl; + if(relayed) + { + auto pathset = ctx->impl.router->paths.GetLocalPathSet(pathID); + if(pathset) + { + return pathset->HandleGotRouterMessage(this); + } + } SearchJob *pending = dht.FindPendingTX(From, txid); if(pending) { @@ -71,7 +79,7 @@ namespace llarp if(pending->requester != dht.OurKey()) { replies.push_back(new GotRouterMessage( - pending->target, pending->requesterTX, &R[0])); + pending->target, pending->requesterTX, &R[0], false)); } } else @@ -101,7 +109,7 @@ namespace llarp if(pending->requester != dht.OurKey()) { replies.push_back(new GotRouterMessage( - pending->target, pending->requesterTX, nullptr)); + pending->target, pending->requesterTX, nullptr, false)); } } } diff --git a/llarp/dht/search_job.cpp b/llarp/dht/search_job.cpp index df9ef01f7..b2ca9acab 100644 --- a/llarp/dht/search_job.cpp +++ b/llarp/dht/search_job.cpp @@ -24,8 +24,9 @@ namespace llarp SearchJob::SearchJob(const Key_t &asker, uint64_t tx, const Key_t &key, const std::set< Key_t > &excludes, - IntroSetHookFunc foundIntroset) + IntroSetHookFunc foundIntroset, DoneFunc done) : foundIntroHook(foundIntroset) + , onDone(done) , started(llarp_time_now_ms()) , requester(asker) , requesterTX(tx) @@ -35,8 +36,9 @@ namespace llarp } SearchJob::SearchJob(const Key_t &asker, uint64_t tx, - IntroSetHookFunc found) + IntroSetHookFunc found, DoneFunc done) : foundIntroHook(found) + , onDone(done) , started(llarp_time_now_ms()) , requester(asker) , requesterTX(tx) @@ -44,12 +46,16 @@ namespace llarp target.Zero(); } - void + bool SearchJob::FoundIntros( const std::vector< llarp::service::IntroSet > &introsets) const { - if(foundIntroHook) - foundIntroHook(introsets); + if(foundIntroHook && foundIntroHook(introsets)) + { + onDone(); + return true; + } + return foundIntroHook == nullptr; } void diff --git a/llarp/iwp/server.cpp b/llarp/iwp/server.cpp index 4b36399f1..f309f0fff 100644 --- a/llarp/iwp/server.cpp +++ b/llarp/iwp/server.cpp @@ -6,9 +6,9 @@ llarp_link::llarp_link(const llarp_iwp_args& args) , crypto(args.crypto) , logic(args.logic) , worker(args.cryptoworker) + , keyfile(args.keyfile) , m_name("IWP") { - strncpy(keyfile, args.keyfile, sizeof(keyfile)); iwp = llarp_async_iwp_new(crypto, logic, worker); pumpingLogic.store(false); } @@ -206,15 +206,23 @@ llarp_link::PumpLogic() void llarp_link::RemoveSession(llarp_link_session* s) { - lock_t lock(m_sessions_Mutex); - auto itr = m_sessions.find(s->addr); - if(itr != m_sessions.end()) { - UnmapAddr(s->addr); - s->done(); - m_sessions.erase(itr); - delete s; + lock_t lock(m_sessions_Mutex); + auto itr = m_sessions.find(s->addr); + if(itr != m_sessions.end()) + { + UnmapAddr(s->addr); + s->done(); + m_sessions.erase(itr); + } + } + { + lock_t lock(m_PendingSessions_Mutex); + auto itr = m_PendingSessions.find(s->addr); + if(itr != m_PendingSessions.end()) + m_PendingSessions.erase(itr); } + delete s; } uint8_t* @@ -230,7 +238,7 @@ llarp_link::ensure_privkey() std::error_code ec; if(!fs::exists(keyfile, ec)) { - if(!keygen(keyfile)) + if(!keygen(keyfile.c_str())) return false; } std::ifstream f(keyfile); diff --git a/llarp/iwp/session.cpp b/llarp/iwp/session.cpp index 3c56debb8..003a50ec6 100644 --- a/llarp/iwp/session.cpp +++ b/llarp/iwp/session.cpp @@ -1,9 +1,9 @@ #ifdef _MSC_VER #define NOMINMAX #endif -#include #include #include +#include #include #include #include "address_info.hpp" diff --git a/llarp/mem.hpp b/llarp/mem.hpp index 9c6f41e84..67cfa310d 100644 --- a/llarp/mem.hpp +++ b/llarp/mem.hpp @@ -23,7 +23,7 @@ namespace llarp } } - template < typename T, size_t align = 8 > + template < typename T, size_t align = 128 > void DumpBuffer(const T &buff) { diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index 40b694067..116740738 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -132,7 +132,7 @@ struct llarp_nodedb llarp_rc entry; llarp::Zero(&entry, sizeof(entry)); llarp_rc_copy(&entry, rc); - entries[pk] = entry; + entries.insert(std::make_pair(pk, entry)); if(llarp_rc_bencode(&entry, &buf)) { @@ -273,8 +273,9 @@ disk_threadworker_setRC(void *user) llarp_async_verify_rc *verify_request = static_cast< llarp_async_verify_rc * >(user); verify_request->valid = verify_request->nodedb->setRC(&verify_request->rc); - llarp_logic_queue_job(verify_request->logic, - {verify_request, &logic_threadworker_callback}); + if(verify_request->logic) + llarp_logic_queue_job(verify_request->logic, + {verify_request, &logic_threadworker_callback}); } // we run the crypto verify in the crypto threadpool worker diff --git a/llarp/path.cpp b/llarp/path.cpp index bf433625b..9536473b9 100644 --- a/llarp/path.cpp +++ b/llarp/path.cpp @@ -263,6 +263,29 @@ namespace llarp builder->Tick(now, m_Router); } + routing::IMessageHandler* + PathContext::GetHandler(const PathID_t& id) + { + routing::IMessageHandler* h = nullptr; + auto pathset = GetLocalPathSet(id); + if(pathset) + { + h = pathset->GetPathByID(id); + } + if(h) + return h; + RouterID us(OurRouterID()); + auto& map = m_TransitPaths; + std::unique_lock< std::mutex > lock(map.first); + auto range = map.second.equal_range(id); + for(auto i = range.first; i != range.second; ++i) + { + if(i->second->info.upstream == us) + return i->second; + } + return nullptr; + } + void PathContext::AddPathBuilder(llarp_pathbuilder_context* ctx) { @@ -366,7 +389,10 @@ namespace llarp msg->X = buf; msg->Y = Y; msg->pathid = TXID(); - return r->SendToOrQueue(Upstream(), msg); + if(r->SendToOrQueue(Upstream(), msg)) + return true; + llarp::LogError("send to ", Upstream(), " failed"); + return false; } bool @@ -411,7 +437,11 @@ namespace llarp byte_t tmp[MAX_LINK_MSG_SIZE / 2]; auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); if(!msg->BEncode(&buf)) + { + llarp::LogError("Bencode failed"); + llarp::DumpBuffer(buf); return false; + } // make nonce TunnelNonce N; N.Randomize(); diff --git a/llarp/pathset.cpp b/llarp/pathset.cpp index 530e5e703..dba386213 100644 --- a/llarp/pathset.cpp +++ b/llarp/pathset.cpp @@ -81,6 +81,19 @@ namespace llarp return nullptr; } + Path* + PathSet::GetPathByID(const PathID_t& id) const + { + auto itr = m_Paths.begin(); + while(itr != m_Paths.end()) + { + if(itr->second->RXID() == id) + return itr->second; + ++itr; + } + return nullptr; + } + size_t PathSet::NumInStatus(PathStatus st) const { diff --git a/llarp/proofofwork.cpp b/llarp/proofofwork.cpp index 9aeaa2608..0c6081a92 100644 --- a/llarp/proofofwork.cpp +++ b/llarp/proofofwork.cpp @@ -9,13 +9,6 @@ namespace llarp { } - bool - PoW::BDecode(llarp_buffer_t* buf) - { - // TODO: implement me - return false; - } - bool PoW::DecodeKey(llarp_buffer_t k, llarp_buffer_t* val) { @@ -27,7 +20,9 @@ namespace llarp PoW::BEncode(llarp_buffer_t* buf) const { // TODO: implement me - return false; + if(!bencode_start_dict(buf)) + return false; + return bencode_end(buf); } bool diff --git a/llarp/router.cpp b/llarp/router.cpp index 517a46ef1..068760abf 100644 --- a/llarp/router.cpp +++ b/llarp/router.cpp @@ -1,6 +1,6 @@ #include "router.hpp" -#include #include +#include #include #include "llarp/iwp/establish_job.hpp" #include "llarp/iwp/server.hpp" @@ -745,10 +745,10 @@ llarp_router::InitOutboundLink() return true; llarp_iwp_args args = { - &crypto, logic, tp, this, transport_keyfile.string().c_str(), + &crypto, logic, tp, this, transport_keyfile.string(), }; - auto link = new(std::nothrow) llarp_link(args); + auto link = new llarp_link(args); auto afs = {AF_INET, AF_INET6}; @@ -1093,6 +1093,7 @@ namespace llarp const char *key, const char *val) { llarp_router *self = static_cast< llarp_router * >(iter->user); + int af; uint16_t proto; if(StrEq(val, "eth")) @@ -1117,17 +1118,15 @@ namespace llarp { if(!StrEq(key, "*")) { - llarp::LogInfo("interface specific binding activated"); - llarp_iwp_args args = { &self->crypto, self->logic, self->tp, self, - self->transport_keyfile.string().c_str(), + self->transport_keyfile.string(), }; - - link = new(std::nothrow) llarp_link(args); + llarp::LogInfo("interface specific binding activated"); + link = new llarp_link(args); if(link) { diff --git a/llarp/service.cpp b/llarp/service.cpp index f2e75fbfb..8104e4cf5 100644 --- a/llarp/service.cpp +++ b/llarp/service.cpp @@ -161,7 +161,6 @@ namespace llarp bool Identity::BEncode(llarp_buffer_t* buf) const { - /// TODO: implement me if(!bencode_start_dict(buf)) return false; if(!BEncodeWriteDictEntry("e", enckey, buf)) @@ -195,10 +194,8 @@ namespace llarp { crypto->encryption_keygen(enckey); crypto->identity_keygen(signkey); - pub.enckey = llarp::seckey_topublic(enckey); - pub.signkey = llarp::seckey_topublic(signkey); - pub.vanity.Zero(); - pub.UpdateAddr(); + pub.Update(llarp::seckey_topublic(enckey), + llarp::seckey_topublic(signkey)); } bool @@ -273,7 +270,7 @@ namespace llarp // rewind and resize buffer buf.sz = buf.cur - buf.base; buf.cur = buf.base; - return crypto->verify(A.signkey, buf, Z); + return A.Verify(crypto, buf, Z); } bool diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 7f84db452..c5a315fb3 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -68,7 +68,6 @@ namespace llarp { if(context) { - llarp::LogInfo("BEEP"); byte_t tmp[128] = {0}; memcpy(tmp, "BEEP", 4); auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); @@ -441,7 +440,7 @@ namespace llarp Endpoint::CachedTagResult::BuildRequestMessage() { llarp::routing::DHTMessage* msg = new llarp::routing::DHTMessage(); - msg->M.push_back(new llarp::dht::FindIntroMessage({}, tag, txid)); + msg->M.push_back(new llarp::dht::FindIntroMessage(tag, txid)); lastRequest = llarp_time_now_ms(); parent->PutLookup(this, txid); return msg; @@ -450,7 +449,7 @@ namespace llarp bool Endpoint::PublishIntroSet(llarp_router* r) { - auto path = GetEstablishedPathClosestTo(m_Identity.pub.Addr()); + auto path = GetEstablishedPathClosestTo(m_Identity.pub.Addr().ToRouter()); if(path) { m_CurrentPublishTX = llarp_randint(); @@ -496,12 +495,13 @@ namespace llarp struct HiddenServiceAddressLookup : public IServiceLookup { Address remote; - Endpoint* endpoint; + typedef std::function< bool(const IntroSet*) > HandlerFunc; + HandlerFunc handle; - HiddenServiceAddressLookup(Endpoint* p, const Address& addr, uint64_t tx) - : IServiceLookup(p, tx), remote(addr), endpoint(p) + HiddenServiceAddressLookup(Endpoint* p, HandlerFunc h, + const Address& addr, uint64_t tx) + : IServiceLookup(p, tx), remote(addr), handle(h) { - llarp::LogInfo("New hidden service lookup for ", addr.ToString()); } bool @@ -512,12 +512,13 @@ namespace llarp { llarp::LogInfo("hidden service lookup for ", remote.ToString(), " success"); - endpoint->PutNewOutboundContext(*results.begin()); + handle(&*results.begin()); } else { llarp::LogInfo("no response in hidden service lookup for ", remote.ToString()); + handle(nullptr); } delete this; return true; @@ -527,7 +528,10 @@ namespace llarp BuildRequestMessage() { llarp::routing::DHTMessage* msg = new llarp::routing::DHTMessage(); - msg->M.push_back(new llarp::dht::FindIntroMessage(remote, txid)); + auto FIM = new llarp::dht::FindIntroMessage(txid, remote); + FIM->R = 5; + msg->M.push_back(FIM); + llarp::LogInfo("build request for ", remote); return msg; } }; @@ -543,7 +547,7 @@ namespace llarp Endpoint::PutNewOutboundContext(const llarp::service::IntroSet& introset) { Address addr; - introset.A.CalculateAddress(addr); + introset.A.CalculateAddress(addr.data()); // only add new session if it's not there if(m_RemoteSessions.find(addr) == m_RemoteSessions.end()) @@ -562,6 +566,55 @@ namespace llarp } } + bool + Endpoint::HandleGotRouterMessage(const llarp::dht::GotRouterMessage* msg) + { + bool success = false; + if(msg->R.size() == 1) + { + auto itr = m_PendingRouters.find(msg->R[0].pubkey); + if(itr == m_PendingRouters.end()) + return false; + llarp_async_verify_rc* job = new llarp_async_verify_rc; + job->nodedb = m_Router->nodedb; + job->cryptoworker = m_Router->tp; + job->diskworker = m_Router->disk; + job->logic = nullptr; + job->hook = nullptr; + llarp_rc_clear(&job->rc); + llarp_rc_copy(&job->rc, &msg->R[0]); + llarp_nodedb_async_verify(job); + return true; + } + return success; + } + + void + Endpoint::EnsureRouterIsKnown(const RouterID& router) + { + if(!llarp_nodedb_get_rc(m_Router->nodedb, router)) + { + if(m_PendingRouters.find(router) == m_PendingRouters.end()) + { + auto path = GetEstablishedPathClosestTo(router); + routing::DHTMessage msg; + auto txid = GenTXID(); + msg.M.push_back( + new dht::FindRouterMessage({}, dht::Key_t(router), txid)); + + if(path->SendRoutingMessage(&msg, m_Router)) + { + llarp::LogInfo(Name(), " looking up ", router); + m_PendingRouters.insert(std::make_pair(router, txid)); + } + else + { + llarp::LogError("failed to send request for router lookup"); + } + } + } + } + void Endpoint::HandlePathBuilt(path::Path* p) { @@ -597,11 +650,20 @@ namespace llarp return m_Parent->HandleHiddenServiceFrame(frame); } + bool + Endpoint::OnOutboundLookup(const IntroSet* introset) + { + if(!introset) + return false; + PutNewOutboundContext(*introset); + return true; + } + bool Endpoint::EnsurePathToService(const Address& remote, PathEnsureHook hook, llarp_time_t timeoutMS) { - auto path = GetEstablishedPathClosestTo(remote); + auto path = GetEstablishedPathClosestTo(remote.ToRouter()); if(!path) { llarp::LogWarn("No outbound path for lookup yet"); @@ -627,10 +689,15 @@ namespace llarp m_PendingServiceLookups.insert(std::make_pair(remote, hook)); - HiddenServiceAddressLookup* job = - new HiddenServiceAddressLookup(this, remote, GenTXID()); + HiddenServiceAddressLookup* job = new HiddenServiceAddressLookup( + this, + std::bind(&Endpoint::OnOutboundLookup, this, std::placeholders::_1), + remote, GenTXID()); - return job->SendRequestViaPath(path, Router()); + if(job->SendRequestViaPath(path, Router())) + return true; + llarp::LogError("send via path failed"); + return false; } Endpoint::OutboundContext::OutboundContext(const IntroSet& intro, @@ -649,51 +716,27 @@ namespace llarp { } - void - Endpoint::OutboundContext::ShiftIntroduction() + bool + Endpoint::OutboundContext::OnIntroSetUpdate(const IntroSet* i) { - for(const auto& intro : currentIntroSet.I) + if(i && i->IsNewerThan(currentIntroSet)) { - if(intro.expiresAt > selectedIntro.expiresAt) - { - selectedIntro = intro; - } + currentIntroSet = *i; } + return true; } - bool - Endpoint::OutboundContext::HandleGotIntroMessage( - const llarp::dht::GotIntroMessage* msg) + void + Endpoint::OutboundContext::ShiftIntroduction() { - if(msg->T != m_UpdateIntrosetTX) - { - llarp::LogError("unwarrented introset message txid=", msg->T); - return false; - } - auto crypto = m_Parent->Crypto(); - if(msg->I.size() == 1) + for(const auto& intro : currentIntroSet.I) { - // found intro set - const auto& introset = msg->I[0]; - if(introset.VerifySignature(crypto) && currentIntroSet.A == introset.A) - { - // update - currentIntroSet = introset; - // reset tx - m_UpdateIntrosetTX = 0; - // shift to newest intro - // TODO: check timestamp on introset to make sure it's new enough - ShiftIntroduction(); - return true; - } - else + m_Parent->EnsureRouterIsKnown(selectedIntro.router); + if(intro.expiresAt > selectedIntro.expiresAt) { - llarp::LogError("Signature Error for intro set ", introset); - return false; + selectedIntro = intro; } } - llarp::LogError("Bad number of intro sets in response"); - return false; } void @@ -761,7 +804,8 @@ namespace llarp // set our introduction self->msg.introReply = self->intro; // derive session key - self->crypto->dh_server(self->sharedKey, self->remote.enckey, + self->crypto->dh_server(self->sharedKey, + self->remote.EncryptionPublicKey(), self->m_LocalIdentity->enckey, self->frame.N); // encrypt and sign @@ -827,17 +871,18 @@ namespace llarp void Endpoint::OutboundContext::UpdateIntroSet() { - auto path = GetEstablishedPathClosestTo(currentIntroSet.A.Addr()); + auto addr = currentIntroSet.A.Addr(); + auto path = m_Parent->GetEstablishedPathClosestTo(addr.ToRouter()); if(path) { - if(m_UpdateIntrosetTX == 0) - { - m_UpdateIntrosetTX = llarp_randint(); - routing::DHTMessage msg; - msg.M.push_back(new llarp::dht::FindIntroMessage( - currentIntroSet.A.Addr(), m_UpdateIntrosetTX)); - path->SendRoutingMessage(&msg, m_Parent->Router()); - } + HiddenServiceAddressLookup* job = new HiddenServiceAddressLookup( + m_Parent, + std::bind(&Endpoint::OutboundContext::OnIntroSetUpdate, this, + std::placeholders::_1), + addr, m_Parent->GenTXID()); + + if(!job->SendRequestViaPath(path, m_Parent->Router())) + llarp::LogError("send via path failed"); } else { @@ -924,7 +969,8 @@ namespace llarp msg.sender = m_Parent->m_Identity.pub; msg.PutBuffer(payload); - if(!f.EncryptAndSign(crypto, &msg, shared, currentIntroSet.A.signkey)) + if(!f.EncryptAndSign(crypto, &msg, shared, + m_Parent->m_Identity.signkey)) { llarp::LogError("failed to sign"); return; diff --git a/llarp/service/info.cpp b/llarp/service/info.cpp index 6545bdb7d..b644976df 100644 --- a/llarp/service/info.cpp +++ b/llarp/service/info.cpp @@ -6,16 +6,6 @@ namespace llarp { namespace service { - ServiceInfo::ServiceInfo() - { - vanity.Zero(); - m_CachedAddr.Zero(); - } - - ServiceInfo::~ServiceInfo() - { - } - bool ServiceInfo::DecodeKey(llarp_buffer_t key, llarp_buffer_t* val) { @@ -56,7 +46,7 @@ namespace llarp if(m_CachedAddr.IsZero()) { Address addr; - CalculateAddress(addr); + CalculateAddress(addr.data()); return addr.ToString(); } return m_CachedAddr.ToString(); @@ -65,9 +55,10 @@ namespace llarp bool ServiceInfo::CalculateAddress(byte_t* addr) const { - byte_t tmp[128]; - auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); - assert(BEncode(&buf)); + byte_t tmp[256] = {0}; + auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); + if(!BEncode(&buf)) + return false; return crypto_generichash(addr, 32, buf.base, buf.cur - buf.base, nullptr, 0) != -1; @@ -76,7 +67,7 @@ namespace llarp bool ServiceInfo::UpdateAddr() { - return CalculateAddress(m_CachedAddr); + return CalculateAddress(m_CachedAddr.data()); } } // namespace service diff --git a/llarp/service/protocol.cpp b/llarp/service/protocol.cpp index 2bb6a481a..fc1d0b2c4 100644 --- a/llarp/service/protocol.cpp +++ b/llarp/service/protocol.cpp @@ -94,8 +94,6 @@ namespace llarp { if(!bencode_start_dict(buf)) return false; - if(!BEncodeWriteDictMsgType(buf, "A", "H")) - return false; if(!BEncodeWriteDictEntry("D", D, buf)) return false; if(S == 0) @@ -261,7 +259,7 @@ namespace llarp llarp::LogError("No sender for T=", T); return false; } - if(!Verify(crypto, si.signkey)) + if(!Verify(crypto, si)) { llarp::LogError("Signature failure"); return false; @@ -289,7 +287,7 @@ namespace llarp } bool - ProtocolFrame::Verify(llarp_crypto* crypto, byte_t* signkey) const + ProtocolFrame::Verify(llarp_crypto* crypto, const ServiceInfo& from) const { ProtocolFrame copy(*this); // save signature @@ -305,7 +303,7 @@ namespace llarp buf.sz = buf.cur - buf.base; buf.cur = buf.base; // verify - result = crypto->verify(Z, buf, signkey); + result = from.Verify(crypto, buf, Z); } // restore signature return result; diff --git a/test/hiddenservice_unittest.cpp b/test/hiddenservice_unittest.cpp index 7489fe711..c063c0fd7 100644 --- a/test/hiddenservice_unittest.cpp +++ b/test/hiddenservice_unittest.cpp @@ -21,7 +21,7 @@ struct HiddenServiceTest : public ::testing::Test SetUp() { ident.RegenerateKeys(Crypto()); - ident.pub.vanity.Randomize(); + ident.pub.RandomizeVanity(); ident.pub.UpdateAddr(); } }; @@ -29,7 +29,7 @@ struct HiddenServiceTest : public ::testing::Test TEST_F(HiddenServiceTest, TestGenerateIntroSet) { llarp::service::Address addr; - ASSERT_TRUE(ident.pub.CalculateAddress(addr)); + ASSERT_TRUE(ident.pub.CalculateAddress(addr.data())); llarp::service::IntroSet I; while(I.I.size() < 10) {