diff --git a/doc/dht_v0.txt b/doc/dht_v0.txt index 00b36854c..beddfb2c5 100644 --- a/doc/dht_v0.txt +++ b/doc/dht_v0.txt @@ -102,6 +102,7 @@ R is currently set to 0 by the sender. I: IS, R: r_counter, S: optional member 0 for immediate store otherwise non zero, + T: transaction_id_uint64, V: 0 } diff --git a/include/llarp/bencode.hpp b/include/llarp/bencode.hpp index 0a9f5acf4..0027ffea0 100644 --- a/include/llarp/bencode.hpp +++ b/include/llarp/bencode.hpp @@ -34,10 +34,6 @@ namespace llarp return bencode_write_bytestring(buf, k, 1) && bencode_write_uint64(buf, i); } - template < typename Item_t > - bool - BEncodeRead(Item_t& item, llarp_buffer_t* buf); - template < typename Item_t > bool BEncodeMaybeReadDictEntry(const char* k, Item_t& item, bool& read, @@ -153,6 +149,27 @@ namespace llarp virtual bool BEncode(llarp_buffer_t* buf) const = 0; + + bool + BDecode(llarp_buffer_t* buf) + { + dict_reader r; + r.user = this; + r.on_key = &OnKey; + return bencode_read_dict(buf, &r); + } + + // TODO: check for shadowed values elsewhere + uint64_t version = 0; + + static bool + OnKey(dict_reader* r, llarp_buffer_t* k) + { + if(k) + return static_cast< IBEncodeMessage* >(r->user)->DecodeKey(*k, + r->buffer); + return true; + } }; } // namespace llarp diff --git a/include/llarp/dht.hpp b/include/llarp/dht.hpp index 075d6fee3..f287605a0 100644 --- a/include/llarp/dht.hpp +++ b/include/llarp/dht.hpp @@ -67,18 +67,19 @@ namespace llarp struct ISNode { - llarp::service::IntroSet* introset; + llarp::service::IntroSet introset; Key_t ID; - ISNode() : introset(nullptr) + ISNode() { ID.Zero(); } - ISNode(llarp::service::IntroSet* other) : introset(other) + ISNode(const llarp::service::IntroSet& other) { - other->A.CalculateAddress(ID); + introset = other; + other.A.CalculateAddress(ID); } }; @@ -119,7 +120,7 @@ namespace llarp }; }; - struct IMessage + struct IMessage : public llarp::IBEncodeMessage { virtual ~IMessage(){}; @@ -128,12 +129,6 @@ namespace llarp { } - virtual bool - BEncode(llarp_buffer_t* buf) const = 0; - - virtual bool - DecodeKey(llarp_buffer_t key, llarp_buffer_t* val) = 0; - virtual bool HandleMessage(llarp_dht_context* dht, std::vector< IMessage* >& replies) const = 0; @@ -310,13 +305,53 @@ namespace llarp Key_t ourKey; }; + struct FindIntroMessage : public IMessage + { + uint64_t R = 0; + llarp::service::Address S; + uint64_t T = 0; + + ~FindIntroMessage(); + + bool + BEncode(llarp_buffer_t* buf) const; + + bool + DecodeKey(llarp_buffer_t key, llarp_buffer_t* val); + + virtual bool + HandleMessage(llarp_dht_context* ctx, + std::vector< IMessage* >& replies) const; + }; + + /// acknologement to PublishIntroMessage or reply to FinIntroMessage + struct GotIntroMessage : public IMessage + { + std::list< llarp::service::IntroSet > I; + uint64_t T; + + GotIntroMessage(uint64_t tx, const llarp::service::IntroSet* i = nullptr); + + ~GotIntroMessage(); + + bool + BEncode(llarp_buffer_t* buf) const; + + bool + DecodeKey(llarp_buffer_t key, llarp_buffer_t* val); + + virtual bool + HandleMessage(llarp_dht_context* ctx, + std::vector< IMessage* >& replies) const; + }; + struct PublishIntroMessage : public IMessage { llarp::service::IntroSet I; - uint64_t R; - uint64_t S; - bool hasS = false; - uint64_t V; + uint64_t R = 0; + uint64_t S = 0; + uint64_t txID = 0; + bool hasS = false; PublishIntroMessage() : IMessage({}) { } diff --git a/include/llarp/path.hpp b/include/llarp/path.hpp index ec0c1cb74..c11e1dbb0 100644 --- a/include/llarp/path.hpp +++ b/include/llarp/path.hpp @@ -157,6 +157,9 @@ namespace llarp HandlePathLatencyMessage(const llarp::routing::PathLatencyMessage* msg, llarp_router* r); + bool + HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg); + bool HandleDHTMessage(const llarp::dht::IMessage* msg, llarp_router* r); @@ -229,6 +232,9 @@ namespace llarp HandlePathTransferMessage(const llarp::routing::PathTransferMessage* msg, llarp_router* r); + bool + HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg); + bool HandleDHTMessage(const llarp::dht::IMessage* msg, llarp_router* r); @@ -320,6 +326,9 @@ namespace llarp IHopHandler* GetByDownstream(const RouterID& id, const PathID_t& path); + PathSet* + GetLocalPathSet(const PathID_t& id); + bool ForwardLRCM(const RouterID& nextHop, std::deque< EncryptedFrame >& frames); diff --git a/llarp/pathbuilder.hpp b/include/llarp/pathbuilder.hpp similarity index 73% rename from llarp/pathbuilder.hpp rename to include/llarp/pathbuilder.hpp index 1777a3907..13f92015b 100644 --- a/llarp/pathbuilder.hpp +++ b/include/llarp/pathbuilder.hpp @@ -1,6 +1,8 @@ -#ifndef LLARP_PATHFINDER_HPP_ -#define LLARP_PATHFINDER_HPP_ +#ifndef LLARP_PATHBUILDER_HPP_ +#define LLARP_PATHBUILDER_HPP_ #include +#include +#include struct llarp_pathbuilder_context : public llarp::path::PathSet { diff --git a/include/llarp/pathset.hpp b/include/llarp/pathset.hpp index e4ce22924..11754fbbd 100644 --- a/include/llarp/pathset.hpp +++ b/include/llarp/pathset.hpp @@ -1,12 +1,17 @@ #ifndef LLARP_PATHSET_HPP #define LLARP_PATHSET_HPP - +#include #include #include #include namespace llarp { + namespace dht + { + struct GotIntroMessage; + } + namespace path { enum PathStatus @@ -52,6 +57,13 @@ namespace llarp bool ShouldBuildMore() const; + /// return true if we should publish a new hidden service descriptor + bool + ShouldPublishDescriptors() const; + + bool + HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg); + private: typedef std::pair< RouterID, PathID_t > PathInfo_t; typedef std::map< PathInfo_t, Path* > PathMap_t; diff --git a/include/llarp/pow.hpp b/include/llarp/pow.hpp index d03fd2326..b4cbcdb15 100644 --- a/include/llarp/pow.hpp +++ b/include/llarp/pow.hpp @@ -1,34 +1,37 @@ #ifndef LLARP_POW_HPP #define LLARP_POW_HPP -#include #include +#include #include namespace llarp { /// proof of work - struct PoW + struct PoW : public IBEncodeMessage { static constexpr size_t MaxSize = 128; - - RouterID router; - uint64_t version = 0; - uint32_t extendedLifetime = 0; + uint64_t timestamp = 0; + uint32_t extendedLifetime = 0; AlignedBuffer< 32 > nonce; + ~PoW(); + bool - BEncode(llarp_buffer_t* buf) const; + IsValid(llarp_shorthash_func hashfunc) const; bool BDecode(llarp_buffer_t* buf); bool - IsValid(llarp_shorthash_func hashfunc, const RouterID& us) const; + DecodeKey(llarp_buffer_t k, llarp_buffer_t* val); + + bool + BEncode(llarp_buffer_t* buf) const; bool operator==(const PoW& other) const { - return router == other.router && version == other.version + return timestamp == other.timestamp && version == other.version && extendedLifetime == other.extendedLifetime && nonce == other.nonce; } diff --git a/include/llarp/routing/handler.hpp b/include/llarp/routing/handler.hpp index faff30578..e11ef4fda 100644 --- a/include/llarp/routing/handler.hpp +++ b/include/llarp/routing/handler.hpp @@ -29,9 +29,7 @@ namespace llarp virtual bool HandlePathLatencyMessage(const PathLatencyMessage *msg, llarp_router *r) = 0; - virtual bool - HandleDHTMessage(const llarp::dht::IMessage *msg, llarp_router *r) = 0; }; } // namespace routing diff --git a/include/llarp/service.hpp b/include/llarp/service.hpp index 32b761eb1..752b53676 100644 --- a/include/llarp/service.hpp +++ b/include/llarp/service.hpp @@ -1,12 +1,11 @@ #ifndef LLARP_SERVICE_HPP #define LLARP_SERVICE_HPP -#include -#include -#include -#include -#include - #include +#include +#include +#include +#include +#include #include #include @@ -14,163 +13,18 @@ namespace llarp { namespace service { - constexpr std::size_t MAX_INTROSET_SIZE = 1024; - - // forward declare - struct IntroSet; - - /// hidden service address - typedef llarp::AlignedBuffer< 32 > Address; - std::string AddressToString(const Address& addr); - typedef llarp::AlignedBuffer< 16 > VanityNonce; - - struct ServiceInfo : public llarp::IBEncodeMessage - { - llarp::PubKey enckey; - llarp::PubKey signkey; - uint64_t version = 0; - VanityNonce vanity; - - ServiceInfo(); - - ~ServiceInfo(); - - ServiceInfo& - operator=(const ServiceInfo& other) - { - enckey = other.enckey; - signkey = other.signkey; - version = other.version; - vanity = other.vanity; - return *this; - }; - - friend std::ostream& - operator<<(std::ostream& out, const ServiceInfo& i) - { - return out << "[e=" << i.enckey << " s=" << i.signkey - << " v=" << i.version << " x=" << i.vanity << "]"; - } - - /// calculate our address - bool - CalculateAddress(Address& addr) const; - - bool - BEncode(llarp_buffer_t* buf) const; - - bool - DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf); - }; - - // private keys - struct Identity : public llarp::IBEncodeMessage - { - llarp::SecretKey enckey; - llarp::SecretKey signkey; - uint64_t version = 0; - VanityNonce vanity; - - // public service info - ServiceInfo pub; - - ~Identity(); - - // regenerate secret keys - void - RegenerateKeys(llarp_crypto* c); - - // load from file - bool - LoadFromFile(const std::string& fpath); - - bool - BEncode(llarp_buffer_t* buf) const; - - bool - DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf); - - bool - SignIntroSet(IntroSet& i, llarp_crypto* c) const; - }; - - struct Introduction : public llarp::IBEncodeMessage - { - llarp::PubKey router; - llarp::PathID_t pathID; - uint64_t version = 0; - uint64_t expiresAt; - - ~Introduction(); - - friend std::ostream& - operator<<(std::ostream& out, const Introduction& i) - { - return out << "k=" << i.router << " p=" << i.pathID - << " v=" << i.version << " x=" << i.expiresAt; - } - - bool - BEncode(llarp_buffer_t* buf) const; - - bool - DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf); - - bool - operator<(const Introduction& other) const - { - return expiresAt < other.expiresAt || pathID < other.pathID; - } - }; - - struct IntroSet : public llarp::IBEncodeMessage + struct Config { - ServiceInfo A; - std::set< Introduction > I; - uint64_t V = 0; - llarp::PoW* W = nullptr; - llarp::Signature Z; - - ~IntroSet(); - - IntroSet& - operator=(const IntroSet& other) - { - A = other.A; - I = other.I; - V = other.V; - if(W) - delete W; - W = other.W; - Z = other.Z; - return *this; - } - - friend std::ostream& - operator<<(std::ostream& out, const IntroSet& i) - { - out << "A=[" << i.A << "] I=["; - for(const auto& intro : i.I) - { - out << intro << ","; - } - return out << "] V=" << i.V << " Z=" << i.Z; - } - - bool - BDecode(llarp_buffer_t* buf); - - bool - BEncode(llarp_buffer_t* buf) const; - - bool - DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf); + typedef std::list< std::pair< std::string, std::string > > + section_values_t; + typedef std::pair< std::string, section_values_t > section_t; + std::list< section_t > services; bool - VerifySignature(llarp_crypto* crypto) const; + Load(const std::string& fname); }; }; // namespace service diff --git a/include/llarp/service/Identity.hpp b/include/llarp/service/Identity.hpp new file mode 100644 index 000000000..d7fc45f20 --- /dev/null +++ b/include/llarp/service/Identity.hpp @@ -0,0 +1,49 @@ +#ifndef LLARP_SERVICE_IDENTITY_HPP +#define LLARP_SERVICE_IDENTITY_HPP +#include +#include +#include +#include +#include + +namespace llarp +{ + namespace service + { + // private keys + struct Identity : public llarp::IBEncodeMessage + { + llarp::SecretKey enckey; + llarp::SecretKey signkey; + uint64_t version = 0; + VanityNonce vanity; + + // public service info + ServiceInfo pub; + + ~Identity(); + + // regenerate secret keys + void + RegenerateKeys(llarp_crypto* c); + + // load from file + bool + LoadFromFile(const std::string& fpath); + + bool + BEncode(llarp_buffer_t* buf) const; + + bool + EnsureKeys(const std::string& fpath, llarp_crypto* c); + + bool + DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf); + + bool + SignIntroSet(IntroSet& i, llarp_crypto* c) const; + }; + } // namespace service +} // namespace llarp + +#endif \ No newline at end of file diff --git a/include/llarp/service/Info.hpp b/include/llarp/service/Info.hpp new file mode 100644 index 000000000..a2e316430 --- /dev/null +++ b/include/llarp/service/Info.hpp @@ -0,0 +1,52 @@ +#ifndef LLARP_SERVICE_INFO_HPP +#define LLARP_SERVICE_INFO_HPP +#include +#include +#include + +namespace llarp +{ + namespace service + { + struct ServiceInfo : public llarp::IBEncodeMessage + { + llarp::PubKey enckey; + llarp::PubKey signkey; + uint64_t version = 0; + VanityNonce vanity; + + ServiceInfo(); + + ~ServiceInfo(); + + ServiceInfo& + operator=(const ServiceInfo& other) + { + enckey = other.enckey; + signkey = other.signkey; + version = other.version; + vanity = other.vanity; + return *this; + }; + + friend std::ostream& + operator<<(std::ostream& out, const ServiceInfo& i) + { + return out << "[e=" << i.enckey << " s=" << i.signkey + << " v=" << i.version << " x=" << i.vanity << "]"; + } + + /// calculate our address + bool + CalculateAddress(Address& addr) const; + + bool + BEncode(llarp_buffer_t* buf) const; + + bool + DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf); + }; + } // namespace service +} // namespace llarp + +#endif \ No newline at end of file diff --git a/include/llarp/service/Intro.hpp b/include/llarp/service/Intro.hpp new file mode 100644 index 000000000..fc89e879f --- /dev/null +++ b/include/llarp/service/Intro.hpp @@ -0,0 +1,45 @@ +#ifndef LLARP_SERVICE_INTRO_HPP +#define LLARP_SERVICE_INTRO_HPP +#include +#include +#include + +#include + +namespace llarp +{ + namespace service + { + struct Introduction : public llarp::IBEncodeMessage + { + llarp::PubKey router; + llarp::PathID_t pathID; + uint64_t latency = 0; + uint64_t version = 0; + uint64_t expiresAt; + + ~Introduction(); + + friend std::ostream& + operator<<(std::ostream& out, const Introduction& i) + { + return out << "k=" << i.router << " p=" << i.pathID + << " v=" << i.version << " x=" << i.expiresAt; + } + + bool + BEncode(llarp_buffer_t* buf) const; + + bool + DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf); + + bool + operator<(const Introduction& other) const + { + return expiresAt < other.expiresAt || pathID < other.pathID; + } + }; + } // namespace service +} // namespace llarp + +#endif \ No newline at end of file diff --git a/include/llarp/service/IntroSet.hpp b/include/llarp/service/IntroSet.hpp new file mode 100644 index 000000000..27032118c --- /dev/null +++ b/include/llarp/service/IntroSet.hpp @@ -0,0 +1,63 @@ +#ifndef LLARP_SERVICE_INTROSET_HPP +#define LLARP_SERVICE_INTROSET_HPP +#include +#include +#include +#include +#include +#include + +#include + +namespace llarp +{ + namespace service + { + constexpr std::size_t MAX_INTROSET_SIZE = 1024; + + struct IntroSet : public llarp::IBEncodeMessage + { + ServiceInfo A; + std::list< Introduction > I; + llarp::PoW* W = nullptr; + llarp::Signature Z; + + ~IntroSet(); + + IntroSet& + operator=(const IntroSet& other) + { + A = other.A; + I = other.I; + version = other.version; + if(W) + delete W; + W = other.W; + Z = other.Z; + return *this; + } + + friend std::ostream& + operator<<(std::ostream& out, const IntroSet& i) + { + out << "A=[" << i.A << "] I=["; + for(const auto& intro : i.I) + { + out << intro << ","; + } + return out << "] V=" << i.version << " Z=" << i.Z; + } + + bool + BEncode(llarp_buffer_t* buf) const; + + bool + DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf); + + bool + VerifySignature(llarp_crypto* crypto) const; + }; + } // namespace service +} // namespace llarp + +#endif \ No newline at end of file diff --git a/include/llarp/service/endpoint.hpp b/include/llarp/service/endpoint.hpp new file mode 100644 index 000000000..a0efa4c1a --- /dev/null +++ b/include/llarp/service/endpoint.hpp @@ -0,0 +1,30 @@ +#ifndef LLARP_SERVICE_ENDPOINT_HPP +#define LLARP_SERVICE_ENDPOINT_HPP +#include +#include + +namespace llarp +{ + namespace service + { + struct Endpoint + { + Endpoint(const std::string& nickname, llarp_router* r); + ~Endpoint(); + + bool + SetOption(const std::string& k, const std::string& v); + + bool + Start(); + + private: + llarp_router* m_Router; + llarp_pathbuilder_context* m_PathSet; + std::string m_Keyfile; + Identity m_Identity; + }; + } // namespace service +} // namespace llarp + +#endif \ No newline at end of file diff --git a/include/llarp/service/types.hpp b/include/llarp/service/types.hpp new file mode 100644 index 000000000..394a11eb8 --- /dev/null +++ b/include/llarp/service/types.hpp @@ -0,0 +1,16 @@ +#ifndef LLARP_SERVICE_TYPES_HPP +#define LLARP_SERVICE_TYPES_HPP +#include + +namespace llarp +{ + namespace service + { + /// hidden service address + typedef llarp::AlignedBuffer< 32 > Address; + + typedef llarp::AlignedBuffer< 16 > VanityNonce; + } +} + +#endif \ No newline at end of file diff --git a/llarp/bencode.cpp b/llarp/bencode.cpp index 3c4f2ce51..952f0f6a0 100644 --- a/llarp/bencode.cpp +++ b/llarp/bencode.cpp @@ -81,8 +81,11 @@ bencode_read_integer(struct llarp_buffer_t* buffer, uint64_t* result) buffer->cur++; numbuf[len] = 0; - *result = atol(numbuf); - return *result != -1; + auto num = atol(numbuf); + if(num == -1) + return false; + *result = num; + return true; } bool diff --git a/llarp/config.cpp b/llarp/config.cpp index 9d68e1f0e..a1ea37d4a 100644 --- a/llarp/config.cpp +++ b/llarp/config.cpp @@ -28,6 +28,7 @@ namespace llarp connect = find_section(top, "connect", section_t{}); netdb = find_section(top, "netdb", section_t{}); iwp_links = find_section(top, "bind", section_t{}); + services = find_section(top, "services", section_t{}); return true; } return false; @@ -66,7 +67,8 @@ llarp_config_iter(struct llarp_config *conf, struct llarp_config_iterator *iter) {"network", conf->impl.network}, {"connect", conf->impl.connect}, {"bind", conf->impl.iwp_links}, - {"netdb", conf->impl.netdb}}; + {"netdb", conf->impl.netdb}, + {"services", conf->impl.services}}; for(const auto item : conf->impl.router) iter->visit(iter, "router", item.first.c_str(), item.second.c_str()); diff --git a/llarp/config.hpp b/llarp/config.hpp index 990e074b8..ba2c19b2e 100644 --- a/llarp/config.hpp +++ b/llarp/config.hpp @@ -16,10 +16,12 @@ namespace llarp section_t netdb; section_t iwp_links; section_t connect; + section_t services; bool Load(const char *fname); }; + } // namespace llarp struct llarp_config diff --git a/llarp/dht.cpp b/llarp/dht.cpp index 68902c035..289eecebb 100644 --- a/llarp/dht.cpp +++ b/llarp/dht.cpp @@ -156,9 +156,8 @@ namespace llarp auto path = dht.router->paths.GetByUpstream(K, pathID); if(path) { - llarp::routing::DHTMessage reply; - reply.M.push_back(new GotRouterMessage(K, txid, &dht.router->rc)); - return path->SendRoutingMessage(&reply, dht.router); + replies.push_back(new GotRouterMessage(K, txid, &dht.router->rc)); + return true; } return false; } @@ -177,6 +176,64 @@ namespace llarp } }; + GotIntroMessage::GotIntroMessage(uint64_t tx, + const llarp::service::IntroSet *i) + : IMessage({}), T(tx) + { + if(i) + { + I.push_back(*i); + } + } + + GotIntroMessage::~GotIntroMessage() + { + } + + bool + GotIntroMessage::HandleMessage(llarp_dht_context *ctx, + std::vector< IMessage * > &replies) const + { + // TODO: implement me? + auto path = ctx->impl.router->paths.GetLocalPathSet(pathID); + if(path) + { + return path->HandleGotIntroMessage(this); + } + return false; + } + + bool + GotIntroMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t *buf) + { + if(llarp_buffer_eq(key, "I")) + { + return BEncodeReadList(I, buf); + } + bool read = false; + if(!BEncodeMaybeReadDictInt("T", T, read, key, buf)) + return false; + if(!BEncodeMaybeReadDictInt("V", version, read, key, buf)) + return false; + return read; + } + + bool + GotIntroMessage::BEncode(llarp_buffer_t *buf) const + { + if(!bencode_start_dict(buf)) + return false; + if(!BEncodeWriteDictMsgType(buf, "A", "G")) + return false; + if(!BEncodeWriteDictList("I", I, buf)) + return false; + if(!BEncodeWriteDictInt(buf, "T", T)) + return false; + if(!BEncodeWriteDictInt(buf, "V", version)) + return false; + return bencode_end(buf); + } + PublishIntroMessage::~PublishIntroMessage() { } @@ -196,7 +253,7 @@ namespace llarp if(!bencode_read_integer(val, &S)) return false; } - if(!BEncodeMaybeReadDictInt("V", V, read, key, val)) + if(!BEncodeMaybeReadDictInt("V", version, read, key, val)) return false; return read; } @@ -211,7 +268,15 @@ namespace llarp llarp::LogWarn("invalid introset signature"); return false; } - return false; + if(I.W && !I.W->IsValid(dht.router->crypto.shorthash)) + { + llarp::LogWarn("proof of work not good enough for IntroSet"); + return false; + } + // TODO: make this smarter + dht.services->PutNode(I); + replies.push_back(new GotIntroMessage(txID, &I)); + return true; } bool diff --git a/llarp/path.cpp b/llarp/path.cpp index 30b666182..62bb6f4d6 100644 --- a/llarp/path.cpp +++ b/llarp/path.cpp @@ -1,8 +1,8 @@ #include #include #include +#include #include "buffer.hpp" -#include "pathbuilder.hpp" #include "router.hpp" namespace llarp @@ -181,6 +181,19 @@ namespace llarp [](TransitHop* h) -> IHopHandler* { return h; }); } + PathSet* + PathContext::GetLocalPathSet(const PathID_t& id) + { + auto& map = m_OurPaths; + std::unique_lock< std::mutex > lock(map.first); + auto itr = map.second.find(id); + if(itr != map.second.end()) + { + return itr->second; + } + return nullptr; + } + const byte_t* PathContext::OurRouterID() const { @@ -447,5 +460,6 @@ namespace llarp delete msg; return result; } + } // namespace path } // namespace llarp diff --git a/llarp/pathbuilder.cpp b/llarp/pathbuilder.cpp index ab87d6604..669e76c93 100644 --- a/llarp/pathbuilder.cpp +++ b/llarp/pathbuilder.cpp @@ -1,7 +1,7 @@ #include #include -#include "pathbuilder.hpp" +#include #include "router.hpp" namespace llarp diff --git a/llarp/pathset.cpp b/llarp/pathset.cpp index b2ac9bda9..b9c3abc19 100644 --- a/llarp/pathset.cpp +++ b/llarp/pathset.cpp @@ -86,5 +86,12 @@ namespace llarp " rx=", path->RXID()); } + bool + PathSet::HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg) + { + // TODO: implement me + return false; + } + } // namespace path } // namespace llarp \ No newline at end of file diff --git a/llarp/proofofwork.cpp b/llarp/proofofwork.cpp index ab340106f..9aeaa2608 100644 --- a/llarp/proofofwork.cpp +++ b/llarp/proofofwork.cpp @@ -1,27 +1,43 @@ +#include #include #include #include "buffer.hpp" namespace llarp { + PoW::~PoW() + { + } + bool PoW::BDecode(llarp_buffer_t* buf) { + // TODO: implement me + return false; + } + + bool + PoW::DecodeKey(llarp_buffer_t k, llarp_buffer_t* val) + { + // TODO: implement me return false; } bool PoW::BEncode(llarp_buffer_t* buf) const { + // TODO: implement me return false; } bool - PoW::IsValid(llarp_shorthash_func hashfunc, const RouterID& us) const + PoW::IsValid(llarp_shorthash_func hashfunc) const { - // is it for us? - if(router != us) + auto now = llarp_time_now_ms(); + + if(now - timestamp > (uint64_t(extendedLifetime) * 1000)) return false; + byte_t digest[SHORTHASHSIZE]; byte_t tmp[MaxSize]; auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); diff --git a/llarp/relay_commit.cpp b/llarp/relay_commit.cpp index 6b00c9e95..d36b763cb 100644 --- a/llarp/relay_commit.cpp +++ b/llarp/relay_commit.cpp @@ -247,8 +247,7 @@ namespace llarp return; } if(self->record.work - && self->record.work->IsValid(self->context->Crypto()->shorthash, - self->context->OurRouterID())) + && self->record.work->IsValid(self->context->Crypto()->shorthash)) { llarp::LogInfo("LRCM extended lifetime by ", self->record.work->extendedLifetime, " seconds for ", diff --git a/llarp/router.cpp b/llarp/router.cpp index 1fce8b86e..0d2e54cb4 100644 --- a/llarp/router.cpp +++ b/llarp/router.cpp @@ -1110,6 +1110,38 @@ llarp_findOrCreateEncryption(llarp_crypto *crypto, const char *fpath, return false; } +bool +llarp_router::LoadHiddenServiceConfig(const char *fname) +{ + llarp::LogDebug("opening hidden service config ", fname); + llarp::service::Config conf; + if(!conf.Load(fname)) + return false; + for(const auto &config : conf.services) + { + if(!AddHiddenService(config)) + return false; + } + return true; +} + +bool +llarp_router::AddHiddenService(const llarp::service::Config::section_t &config) +{ + auto service = new llarp::service::Endpoint(config.first, this); + for(const auto &option : config.second) + { + auto &k = option.first; + auto &v = option.second; + if(!service->SetOption(k, v)) + { + delete service; + return false; + } + } + return service->Start(); +} + namespace llarp { void @@ -1183,6 +1215,17 @@ namespace llarp llarp::LogError("link ", key, " failed to configure. (Note: We don't support * yet)"); } + else if(StrEq(section, "services")) + { + if(self->LoadHiddenServiceConfig(val)) + { + llarp::LogInfo("loaded hidden service config for ", key); + } + else + { + llarp::LogWarn("failed to load hidden service config for ", key); + } + } else if(StrEq(section, "connect")) { self->connect[key] = val; @@ -1230,5 +1273,4 @@ namespace llarp } } } - } // namespace llarp diff --git a/llarp/router.hpp b/llarp/router.hpp index 0719c998f..3a06e9ddf 100644 --- a/llarp/router.hpp +++ b/llarp/router.hpp @@ -125,6 +125,12 @@ struct llarp_router void Close(); + bool + LoadHiddenServiceConfig(const char *fname); + + bool + AddHiddenService(const llarp::service::Config::section_t &config); + bool Ready(); diff --git a/llarp/service.cpp b/llarp/service.cpp index 8bc5566c1..80e010843 100644 --- a/llarp/service.cpp +++ b/llarp/service.cpp @@ -1,5 +1,6 @@ #include #include "buffer.hpp" +#include "router.hpp" namespace llarp { @@ -75,29 +76,24 @@ namespace llarp } bool - IntroSet::DecodeKey(llarp_buffer_t key, llarp_buffer_t* val) + IntroSet::DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) { - // TODO: implement me - return false; - } + bool read = false; + if(!BEncodeMaybeReadDictEntry("A", A, read, key, buf)) + return false; - bool - IntroSetDecodeKey(dict_reader* r, llarp_buffer_t* key) - { - IntroSet* self = static_cast< IntroSet* >(r->user); - if(!key) - // TODO: determine if we read anything - return true; - return self->DecodeKey(*key, r->buffer); - } + if(llarp_buffer_eq(key, "I")) + { + return BEncodeReadList(I, buf); + } - bool - IntroSet::BDecode(llarp_buffer_t* buf) - { - dict_reader r; - r.user = this; - r.on_key = &IntroSetDecodeKey; - return bencode_read_dict(buf, &r); + if(!BEncodeMaybeReadDictInt("V", version, read, key, buf)) + return false; + + if(!BEncodeMaybeReadDictEntry("Z", Z, read, key, buf)) + return false; + + return read; } bool @@ -115,7 +111,7 @@ namespace llarp // end introduction list // write version - if(!BEncodeWriteDictInt(buf, "v", V)) + if(!BEncodeWriteDictInt(buf, "v", version)) return false; if(W) { @@ -133,10 +129,20 @@ namespace llarp } bool - Introduction::DecodeKey(llarp_buffer_t key, llarp_buffer_t* val) + Introduction::DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) { - // TODO: implement me - return false; + bool read = false; + if(!BEncodeMaybeReadDictEntry("k", router, read, key, buf)) + return false; + if(!BEncodeMaybeReadDictInt("l", latency, read, key, buf)) + return false; + if(!BEncodeMaybeReadDictEntry("p", pathID, read, key, buf)) + return false; + if(!BEncodeMaybeReadDictInt("v", version, read, key, buf)) + return false; + if(!BEncodeMaybeReadDictInt("x", expiresAt, read, key, buf)) + return false; + return read; } bool @@ -144,8 +150,14 @@ namespace llarp { if(!bencode_start_dict(buf)) return false; + if(!BEncodeWriteDictEntry("k", router, buf)) return false; + if(latency) + { + if(!BEncodeWriteDictInt(buf, "l", latency)) + return false; + } if(!BEncodeWriteDictEntry("p", pathID, buf)) return false; if(!BEncodeWriteDictInt(buf, "v", version)) @@ -216,5 +228,42 @@ namespace llarp return crypto->verify(A.signkey, buf, Z); } + Endpoint::Endpoint(const std::string& name, llarp_router* r) + : m_Router(r), m_PathSet(llarp_pathbuilder_context_new(r, r->dht)) + { + } + + bool + Endpoint::SetOption(const std::string& k, const std::string& v) + { + if(k == "keyfile") + { + m_Keyfile = v; + return true; + } + return false; + } + + bool + Endpoint::Start() + { + auto crypto = &m_Router->crypto; + if(m_Keyfile.size()) + { + if(!m_Identity.EnsureKeys(m_Keyfile, crypto)) + return false; + } + else + { + m_Identity.RegenerateKeys(crypto); + } + return true; + } + + Endpoint::~Endpoint() + { + llarp_pathbuilder_context_free(m_PathSet); + } + } // namespace service } // namespace llarp diff --git a/test/hiddenservice_unittest.cpp b/test/hiddenservice_unittest.cpp index ba6f3e518..058651736 100644 --- a/test/hiddenservice_unittest.cpp +++ b/test/hiddenservice_unittest.cpp @@ -36,7 +36,7 @@ TEST_F(HiddenServiceTest, TestGenerateIntroSet) intro.expiresAt = 1000; intro.router.Randomize(); intro.pathID.Randomize(); - I.I.insert(intro); + I.I.push_back(intro); } ASSERT_TRUE(ident.SignIntroSet(I, Crypto())); ASSERT_TRUE(I.VerifySignature(Crypto()));