diff --git a/Makefile b/Makefile index a2754bf96..88315facf 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ clean: rm -f $(SHADOW_PLUGIN) $(SHADOW_CONFIG) rm -f *.sig -debug-configure: clean +debug-configure: cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DWITH_TESTS=ON -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX) release-configure: clean diff --git a/include/llarp/pathbuilder.h b/include/llarp/pathbuilder.h index 89af36666..6f1332381 100644 --- a/include/llarp/pathbuilder.h +++ b/include/llarp/pathbuilder.h @@ -20,7 +20,8 @@ struct llarp_pathbuilder_context; /// alloc struct llarp_pathbuilder_context* llarp_pathbuilder_context_new(struct llarp_router* router, - struct llarp_dht_context* dht, size_t numpaths); + struct llarp_dht_context* dht, size_t numpaths, + size_t defaultNumHops); /// dealloc void llarp_pathbuilder_context_free(struct llarp_pathbuilder_context* ctx); @@ -30,9 +31,9 @@ struct llarp_pathbuild_job; /// response callback typedef void (*llarp_pathbuilder_hook)(struct llarp_pathbuild_job*); -// select hop function (nodedb, prevhop, result, hopnnumber) called in logic -// thread -typedef void (*llarp_pathbuilder_select_hop_func)(struct llarp_nodedb*, +// select hop function (user, nodedb, prevhop, result, hopnnumber) called in +// logic thread +typedef void (*llarp_pathbuilder_select_hop_func)(void*, struct llarp_nodedb*, struct llarp_rc*, struct llarp_rc*, size_t); diff --git a/include/llarp/pathbuilder.hpp b/include/llarp/pathbuilder.hpp index 618454288..e1866603e 100644 --- a/include/llarp/pathbuilder.hpp +++ b/include/llarp/pathbuilder.hpp @@ -8,12 +8,17 @@ struct llarp_pathbuilder_context : public llarp::path::PathSet { struct llarp_router* router; struct llarp_dht_context* dht; + size_t numHops; /// construct llarp_pathbuilder_context(llarp_router* p_router, - struct llarp_dht_context* p_dht, size_t numPaths); + struct llarp_dht_context* p_dht, size_t numPaths, + size_t numHops); virtual ~llarp_pathbuilder_context(){}; + virtual bool + SelectHop(llarp_nodedb* db, llarp_rc* prev, llarp_rc* cur, size_t hop); + void BuildOne(); }; diff --git a/include/llarp/pathset.hpp b/include/llarp/pathset.hpp index 84e42de9e..19e099abd 100644 --- a/include/llarp/pathset.hpp +++ b/include/llarp/pathset.hpp @@ -91,6 +91,18 @@ namespace llarp return false; } + virtual bool + SelectHop(llarp_nodedb* db, llarp_rc* prev, llarp_rc* cur, + size_t hop) = 0; + + static void + SelectHopCallback(void* user, llarp_nodedb* db, llarp_rc* prev, + llarp_rc* cur, size_t hopno) + { + PathSet* self = static_cast< PathSet* >(user); + self->SelectHop(db, prev, cur, hopno); + } + private: typedef std::pair< RouterID, PathID_t > PathInfo_t; typedef std::map< PathInfo_t, Path* > PathMap_t; diff --git a/include/llarp/service/endpoint.hpp b/include/llarp/service/endpoint.hpp index d00a4c4fc..947907fd7 100644 --- a/include/llarp/service/endpoint.hpp +++ b/include/llarp/service/endpoint.hpp @@ -69,7 +69,7 @@ namespace llarp /// context needed to initiate an outbound hidden service session struct OutboundContext : public llarp_pathbuilder_context { - OutboundContext(Endpoint* parent); + OutboundContext(const IntroSet& introSet, Endpoint* parent); ~OutboundContext(); /// the remote hidden service's curren intro set @@ -83,6 +83,9 @@ namespace llarp void UpdateIntroSet(); + bool + SelectHop(llarp_nodedb* db, llarp_rc* prev, llarp_rc* cur, size_t hop); + bool HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg); @@ -128,6 +131,9 @@ namespace llarp return true; } + void + PutNewOutboundContext(const IntroSet& introset); + protected: virtual void IntroSetPublishFail(); @@ -156,7 +162,7 @@ namespace llarp llarp_time_t m_LastPublishAttempt = 0; /// our introset service::IntroSet m_IntroSet; - /// pending remote service lookups + /// pending remote service lookups by id std::unordered_map< uint64_t, service::IServiceLookup* > m_PendingLookups; /// hidden service tag Tag m_Tag; diff --git a/llarp/dnsc.cpp b/llarp/dnsc.cpp index 6f67b4d20..40b68ebeb 100644 --- a/llarp/dnsc.cpp +++ b/llarp/dnsc.cpp @@ -231,7 +231,7 @@ llarp_handle_dnsclient_recvfrom(struct llarp_udp_io *udp, return; } // it's corrupt by here... - dns_request *server_request = (dns_request *)request->user; + // dns_request *server_request = (dns_request *)request->user; // unsigned char buffer[DNC_BUF_SIZE]; unsigned char *buffer = (unsigned char *)buf; @@ -418,14 +418,14 @@ llarp_dns_resolve(dns_client_request *request) struct sockaddr_in addr; // int socket; ssize_t ret; - socklen_t size; + // socklen_t size; // unsigned char tempBuf[3]; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(SERVER); addr.sin_port = htons(PORT); - size = sizeof(addr); + // size = sizeof(addr); llarp_udp_io *udp = (llarp_udp_io *)request->sock; // llarp::LogDebug("dns client set to use "); @@ -442,7 +442,7 @@ llarp_dns_resolve(dns_client_request *request) llarp::LogWarn("Error Sending Request"); return false; } - dns_request *test = (dns_request *)request->user; + // dns_request *test = (dns_request *)request->user; // printf("Sent\n"); llarp::LogInfo("Request sent, awaiting response"); diff --git a/llarp/pathbuilder.cpp b/llarp/pathbuilder.cpp index 7c5708ece..7b2ec1120 100644 --- a/llarp/pathbuilder.cpp +++ b/llarp/pathbuilder.cpp @@ -156,7 +156,7 @@ namespace llarp { llarp_rc* rc = &job->hops.hops[idx].router; llarp_rc_clear(rc); - job->selectHop(job->router->nodedb, prev, rc, idx); + job->selectHop(job->user, job->router->nodedb, prev, rc, idx); prev = rc; ++idx; } @@ -175,29 +175,39 @@ namespace llarp } // namespace llarp llarp_pathbuilder_context::llarp_pathbuilder_context( - llarp_router* p_router, struct llarp_dht_context* p_dht, size_t pathNum) - : llarp::path::PathSet(pathNum), router(p_router), dht(p_dht) + llarp_router* p_router, struct llarp_dht_context* p_dht, size_t pathNum, + size_t hops) + : llarp::path::PathSet(pathNum), router(p_router), dht(p_dht), numHops(hops) { p_router->paths.AddPathBuilder(this); } +bool +llarp_pathbuilder_context::SelectHop(llarp_nodedb* db, llarp_rc* prev, + llarp_rc* cur, size_t hop) +{ + llarp_nodedb_select_random_hop(db, prev, cur, hop); + return true; +} + void llarp_pathbuilder_context::BuildOne() { llarp_pathbuild_job* job = new llarp_pathbuild_job; job->context = this; - job->selectHop = nullptr; - job->hops.numHops = 4; - job->user = nullptr; + job->selectHop = &PathSet::SelectHopCallback; + job->hops.numHops = numHops; + job->user = this; job->pathBuildStarted = [](llarp_pathbuild_job* j) { delete j; }; llarp_pathbuilder_build_path(job); } struct llarp_pathbuilder_context* llarp_pathbuilder_context_new(struct llarp_router* router, - struct llarp_dht_context* dht, size_t sz) + struct llarp_dht_context* dht, size_t sz, + size_t hops) { - return new llarp_pathbuilder_context(router, dht, sz); + return new llarp_pathbuilder_context(router, dht, sz, hops); } void @@ -214,9 +224,12 @@ llarp_pathbuilder_build_path(struct llarp_pathbuild_job* job) llarp::LogError("failed to build path because no context is set in job"); return; } - job->router = job->context->router; if(job->selectHop == nullptr) - job->selectHop = &llarp_nodedb_select_random_hop; + { + llarp::LogError("No callback provided for hop selection"); + return; + } + job->router = job->context->router; llarp_logic_queue_job(job->router->logic, {job, &llarp::pathbuilder_start_build}); } diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 9a1008158..25f0e2f9f 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -10,7 +10,7 @@ namespace llarp namespace service { Endpoint::Endpoint(const std::string& name, llarp_router* r) - : llarp_pathbuilder_context(r, r->dht, 2), m_Router(r), m_Name(name) + : llarp_pathbuilder_context(r, r->dht, 2, 4), m_Router(r), m_Name(name) { m_Tag.Zero(); } @@ -55,8 +55,8 @@ namespace llarp else { llarp::LogWarn("PathAlignJob timed out"); - delete this; } + delete this; } }; @@ -295,6 +295,29 @@ namespace llarp llarp::LogInfo(Name(), " IntroSet publish confirmed"); } + struct HiddenServiceAddressLookup : public IServiceLookup + { + Endpoint* endpoint; + HiddenServiceAddressLookup(Endpoint* parent) : endpoint(parent) + { + } + + bool + HandleResponse(const std::set< IntroSet >& results) + { + if(results.size() == 0) + { + auto itr = results.begin(); + endpoint->PutNewOutboundContext(*itr); + } + else + { + // TODO: retry request? + } + return true; + } + }; + bool Endpoint::EnsurePathToService(const Address& remote, PathEnsureHook hook, llarp_time_t timeoutMS) @@ -303,10 +326,14 @@ namespace llarp return false; } - Endpoint::OutboundContext::OutboundContext(Endpoint* parent) - : llarp_pathbuilder_context(parent->m_Router, parent->m_Router->dht, 2) + Endpoint::OutboundContext::OutboundContext(const IntroSet& intro, + Endpoint* parent) + : llarp_pathbuilder_context(parent->m_Router, parent->m_Router->dht, 2, + 4) + , currentIntroSet(intro) , m_SendQueue(parent->Name() + "::outbound_queue") , m_Parent(parent) + { } @@ -318,8 +345,23 @@ namespace llarp Endpoint::OutboundContext::HandleGotIntroMessage( const llarp::dht::GotIntroMessage* msg) { - // TODO: implement me - + auto crypto = m_Parent->Crypto(); + if(msg->I.size() == 1) + { + // found intro set + auto itr = msg->I.begin(); + if(itr->VerifySignature(crypto) && currentIntroSet.A == itr->A) + { + currentIntroSet = *itr; + return true; + } + else + { + llarp::LogError("Signature Error for intro set ", *itr); + return false; + } + } + llarp::LogError("Bad number of intro sets in response"); return false; } @@ -391,6 +433,43 @@ namespace llarp // TODO: implement me } + bool + Endpoint::OutboundContext::SelectHop(llarp_nodedb* db, llarp_rc* prev, + llarp_rc* cur, size_t hop) + { + // TODO: don't hard code + if(hop == 3) + { + llarp_time_t lowest = 0xFFFFFFFFFFFFFFFFUL; + Introduction chosen; + // pick intro set with lowest latency + for(const auto& intro : currentIntroSet.I) + { + if(intro.latency < lowest) + { + chosen = intro; + lowest = intro.latency; + } + } + auto localcopy = llarp_nodedb_get_rc(db, chosen.router); + if(localcopy) + { + llarp_rc_copy(cur, localcopy); + return true; + } + else + { + // we don't have it? + llarp::LogError( + "cannot build aligned path, don't have router for introduction ", + chosen); + return false; + } + } + else + return llarp_pathbuilder_context::SelectHop(db, prev, cur, hop); + } + void Endpoint::OutboundContext::AsyncEncrypt( ProtocolMessage* msg, std::function< void(ProtocolMessage*) > result)