From bae4f746be6c21650ee3a9da860ff474c2b5b5a3 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Wed, 11 Jul 2018 12:11:19 -0400 Subject: [PATCH] publish hidden service descriptors and acknoledge publish --- CMakeLists.txt | 2 + contrib/testnet/genconf.py | 14 +++- include/llarp/dht/messages/gotintro.hpp | 8 +- include/llarp/dht/messages/pubintro.hpp | 6 ++ include/llarp/iwp/sendbuf.hpp | 11 ++- include/llarp/path.hpp | 9 ++- include/llarp/pathbuilder.hpp | 2 + include/llarp/pathset.hpp | 20 ++++- include/llarp/routing/message.hpp | 1 + include/llarp/service.hpp | 22 +----- include/llarp/service/Info.hpp | 7 ++ include/llarp/service/Intro.hpp | 10 +++ include/llarp/service/config.hpp | 23 ++++++ include/llarp/service/context.hpp | 30 +++++++ include/llarp/service/endpoint.hpp | 10 ++- llarp/crypto_async.cpp | 10 ++- llarp/dht/decode.cpp | 12 +++ llarp/dht/got_intro.cpp | 7 +- llarp/dht/publish_intro.cpp | 6 +- llarp/iwp/frame_state.cpp | 50 +++++------- llarp/path.cpp | 19 ++++- llarp/pathset.cpp | 61 +++++++++++++- llarp/router.cpp | 29 +------ llarp/router.hpp | 2 + llarp/routing/message_parser.cpp | 5 +- llarp/service.cpp | 56 ++++--------- llarp/service/context.cpp | 64 +++++++++++++++ llarp/service/endpoint.cpp | 101 ++++++++++++++++++++++++ 28 files changed, 456 insertions(+), 141 deletions(-) create mode 100644 include/llarp/service/config.hpp create mode 100644 include/llarp/service/context.hpp create mode 100644 llarp/service/context.cpp create mode 100644 llarp/service/endpoint.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 808ba8ac7..89f9bd4c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,6 +191,8 @@ set(LIB_SRC llarp/routing/path_confirm.cpp llarp/routing/path_latency.cpp llarp/routing/path_transfer.cpp + llarp/service/context.cpp + llarp/service/endpoint.cpp vendor/cppbackport-master/lib/fs/rename.cpp vendor/cppbackport-master/lib/fs/filestatus.cpp vendor/cppbackport-master/lib/fs/filetype.cpp diff --git a/contrib/testnet/genconf.py b/contrib/testnet/genconf.py index 2d7cf5f50..7d2f13d7c 100644 --- a/contrib/testnet/genconf.py +++ b/contrib/testnet/genconf.py @@ -27,6 +27,7 @@ def main(): ap.add_argument('--bin', type=str, required=True) ap.add_argument('--out', type=str, required=True) ap.add_argument('--connect', type=int, default=10) + ap.add_argument('--ifname', type=str, default='lo') args = ap.parse_args() @@ -39,7 +40,7 @@ def main(): 'worker-threads': '4' } config['bind'] = { - 'lo': str(args.baseport + nodeid) + args.ifname: str(args.baseport + nodeid) } config['netdb'] = { 'dir': 'netdb' @@ -60,6 +61,7 @@ def main(): for nodeid in range(args.clients): config = CP() + config['router'] = { 'net-threads': '1', 'worker-threads': '2' @@ -77,9 +79,19 @@ def main(): d = os.path.join(args.dir, clientNodeName(nodeid)) if not os.path.exists(d): os.mkdir(d) + hiddenservice = os.path.join(d, 'service.ini') + config['services'] = { + 'testnet': hiddenservice + } fp = os.path.join(d, 'daemon.ini') with open(fp, 'w') as f: config.write(f) + config = CP() + config['test-service'] = { + + } + with open(hiddenservice, 'w') as f: + config.write(f) with open(args.out, 'w') as f: f.write('''[program:svc-node] diff --git a/include/llarp/dht/messages/gotintro.hpp b/include/llarp/dht/messages/gotintro.hpp index 3358eb7be..ca75d75dc 100644 --- a/include/llarp/dht/messages/gotintro.hpp +++ b/include/llarp/dht/messages/gotintro.hpp @@ -11,7 +11,11 @@ namespace llarp struct GotIntroMessage : public IMessage { std::list< llarp::service::IntroSet > I; - uint64_t T; + uint64_t T = 0; + + GotIntroMessage() : IMessage({}) + { + } GotIntroMessage(uint64_t tx, const llarp::service::IntroSet* i = nullptr); @@ -23,7 +27,7 @@ namespace llarp bool DecodeKey(llarp_buffer_t key, llarp_buffer_t* val); - virtual bool + bool HandleMessage(llarp_dht_context* ctx, std::vector< IMessage* >& replies) const; }; diff --git a/include/llarp/dht/messages/pubintro.hpp b/include/llarp/dht/messages/pubintro.hpp index 4a34f223c..dffa121b2 100644 --- a/include/llarp/dht/messages/pubintro.hpp +++ b/include/llarp/dht/messages/pubintro.hpp @@ -17,6 +17,12 @@ namespace llarp { } + PublishIntroMessage(const llarp::service::IntroSet& i, uint64_t tx) + : IMessage({}), txID(tx) + { + I = i; + } + ~PublishIntroMessage(); bool diff --git a/include/llarp/iwp/sendbuf.hpp b/include/llarp/iwp/sendbuf.hpp index 30a139059..88a52fbb6 100644 --- a/include/llarp/iwp/sendbuf.hpp +++ b/include/llarp/iwp/sendbuf.hpp @@ -8,15 +8,15 @@ struct sendbuf_t { sendbuf_t(size_t s) : sz(s) { - buf = new byte_t[s]; + _buf = new byte_t[s]; } ~sendbuf_t() { - delete[] buf; + if(_buf) + delete[] _buf; } - byte_t *buf; size_t sz; size_t @@ -28,8 +28,11 @@ struct sendbuf_t byte_t * data() { - return buf; + return _buf; } + + private: + byte_t *_buf = nullptr; }; typedef std::queue< sendbuf_t * > sendqueue_t; \ No newline at end of file diff --git a/include/llarp/path.hpp b/include/llarp/path.hpp index 1ef6e8055..6ea399759 100644 --- a/include/llarp/path.hpp +++ b/include/llarp/path.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -204,6 +205,9 @@ namespace llarp typedef std::function< void(Path*) > BuildResultHookFunc; typedef std::vector< PathHopConfig > HopList; HopList hops; + + llarp::service::Introduction intro; + llarp_time_t buildStarted; PathStatus status; @@ -253,6 +257,9 @@ namespace llarp bool HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r); + bool + IsReady() const; + // Is this deprecated? // nope not deprecated :^DDDD const PathID_t& @@ -264,8 +271,6 @@ namespace llarp RouterID Upstream() const; - llarp_time_t Latency = 0; - protected: llarp::routing::InboundMessageParser m_InboundMessageParser; diff --git a/include/llarp/pathbuilder.hpp b/include/llarp/pathbuilder.hpp index 13f92015b..80704249a 100644 --- a/include/llarp/pathbuilder.hpp +++ b/include/llarp/pathbuilder.hpp @@ -12,6 +12,8 @@ struct llarp_pathbuilder_context : public llarp::path::PathSet llarp_pathbuilder_context(llarp_router* p_router, struct llarp_dht_context* p_dht); + virtual ~llarp_pathbuilder_context(){}; + void BuildOne(); }; diff --git a/include/llarp/pathset.hpp b/include/llarp/pathset.hpp index 11754fbbd..d0155abbf 100644 --- a/include/llarp/pathset.hpp +++ b/include/llarp/pathset.hpp @@ -1,7 +1,10 @@ #ifndef LLARP_PATHSET_HPP #define LLARP_PATHSET_HPP #include +#include #include +#include +#include #include #include @@ -61,8 +64,22 @@ namespace llarp bool ShouldPublishDescriptors() const; + virtual bool + HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg) + { + return false; + } + + Path* + PickRandomEstablishedPath(); + + bool + GetCurrentIntroductions( + std::list< llarp::service::Introduction >& intros) const; + bool - HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg); + PublishIntroSet(const llarp::service::IntroSet& introset, + llarp_router* r); private: typedef std::pair< RouterID, PathID_t > PathInfo_t; @@ -70,6 +87,7 @@ namespace llarp size_t m_NumPaths; PathMap_t m_Paths; + uint64_t m_CurrentPublishTX = 0; }; } // namespace path diff --git a/include/llarp/routing/message.hpp b/include/llarp/routing/message.hpp index f1cb9ee68..f7b59d701 100644 --- a/include/llarp/routing/message.hpp +++ b/include/llarp/routing/message.hpp @@ -22,6 +22,7 @@ namespace llarp struct InboundMessageParser { + llarp::PathID_t from; InboundMessageParser(); bool ParseMessageBuffer(llarp_buffer_t buf, IMessageHandler* handler, diff --git a/include/llarp/service.hpp b/include/llarp/service.hpp index df596f905..c8854d8af 100644 --- a/include/llarp/service.hpp +++ b/include/llarp/service.hpp @@ -4,27 +4,9 @@ #include #include #include +#include +#include #include #include -#include -#include - -namespace llarp -{ - namespace service - { - struct Config - { - 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 - Load(const std::string& fname); - }; - - }; // 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 index a2e316430..cf15bbd22 100644 --- a/include/llarp/service/Info.hpp +++ b/include/llarp/service/Info.hpp @@ -19,6 +19,13 @@ namespace llarp ~ServiceInfo(); + bool + operator==(const ServiceInfo& other) const + { + return enckey == other.enckey && signkey == other.signkey + && version == other.version && vanity == other.vanity; + } + ServiceInfo& operator=(const ServiceInfo& other) { diff --git a/include/llarp/service/Intro.hpp b/include/llarp/service/Intro.hpp index fc89e879f..1c22f8d00 100644 --- a/include/llarp/service/Intro.hpp +++ b/include/llarp/service/Intro.hpp @@ -18,6 +18,16 @@ namespace llarp uint64_t version = 0; uint64_t expiresAt; + Introduction() = default; + Introduction(const Introduction& other) + { + router = other.router; + pathID = other.pathID; + latency = other.latency; + version = other.version; + expiresAt = other.expiresAt; + } + ~Introduction(); friend std::ostream& diff --git a/include/llarp/service/config.hpp b/include/llarp/service/config.hpp new file mode 100644 index 000000000..e317008d5 --- /dev/null +++ b/include/llarp/service/config.hpp @@ -0,0 +1,23 @@ +#ifndef LLARP_SERVICE_CONFIG_HPP +#define LLARP_SERVICE_CONFIG_HPP +#include +#include + +namespace llarp +{ + namespace service + { + struct Config + { + 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 + Load(const std::string& fname); + }; + } +} +#endif \ No newline at end of file diff --git a/include/llarp/service/context.hpp b/include/llarp/service/context.hpp new file mode 100644 index 000000000..887d93ca4 --- /dev/null +++ b/include/llarp/service/context.hpp @@ -0,0 +1,30 @@ +#ifndef LLARP_SERVICE_CONTEXT_HPP +#define LLARP_SERVICE_CONTEXT_HPP +#include +#include +#include +#include + +namespace llarp +{ + namespace service + { + /// holds all the hidden service endpoints we own + struct Context + { + Context(llarp_router *r); + ~Context(); + + void + Tick(); + + bool + AddEndpoint(const Config::section_t &conf); + + private: + llarp_router *m_Router; + std::unordered_map< std::string, Endpoint * > m_Endpoints; + }; + } +} +#endif \ No newline at end of file diff --git a/include/llarp/service/endpoint.hpp b/include/llarp/service/endpoint.hpp index a0efa4c1a..ca2ff36db 100644 --- a/include/llarp/service/endpoint.hpp +++ b/include/llarp/service/endpoint.hpp @@ -7,7 +7,7 @@ namespace llarp { namespace service { - struct Endpoint + struct Endpoint : public llarp_pathbuilder_context { Endpoint(const std::string& nickname, llarp_router* r); ~Endpoint(); @@ -15,13 +15,19 @@ namespace llarp bool SetOption(const std::string& k, const std::string& v); + void + Tick(); + bool Start(); + bool + HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg); + private: llarp_router* m_Router; - llarp_pathbuilder_context* m_PathSet; std::string m_Keyfile; + std::string m_Name; Identity m_Identity; }; } // namespace service diff --git a/llarp/crypto_async.cpp b/llarp/crypto_async.cpp index 5abfeb11e..8773be0bf 100644 --- a/llarp/crypto_async.cpp +++ b/llarp/crypto_async.cpp @@ -208,6 +208,7 @@ namespace iwp iwp_async_session_start *session = static_cast< iwp_async_session_start * >(user); auto crypto = session->iwp->crypto; + auto logic = session->iwp->logic; auto dh = crypto->transport_dh_client; auto shorthash = crypto->shorthash; @@ -248,8 +249,8 @@ namespace iwp buf.base = (session->buf + 32); buf.sz = session->sz - 32; hmac(session->buf, buf, e_K); - session->hook(session); - // llarp_logic_queue_job(logic, {user, &inform_session_start}); + // session->hook(session); + llarp_logic_queue_job(logic, {user, &inform_session_start}); } void @@ -258,6 +259,7 @@ namespace iwp iwp_async_session_start *session = static_cast< iwp_async_session_start * >(user); auto crypto = session->iwp->crypto; + auto logic = session->iwp->logic; auto dh = crypto->transport_dh_server; auto shorthash = crypto->shorthash; @@ -313,8 +315,8 @@ namespace iwp } else // hmac fail session->buf = nullptr; - session->hook(session); - // llarp_logic_queue_job(logic, {user, &inform_session_start}); + // session->hook(session); + llarp_logic_queue_job(logic, {user, &inform_session_start}); } void diff --git a/llarp/dht/decode.cpp b/llarp/dht/decode.cpp index e10545102..ad99dd249 100644 --- a/llarp/dht/decode.cpp +++ b/llarp/dht/decode.cpp @@ -57,6 +57,18 @@ namespace llarp case 'I': dec->msg = new PublishIntroMessage(); break; + case 'G': + if(dec->relayed) + { + dec->msg = new GotIntroMessage(); + break; + } + else + { + llarp::LogWarn( + "GotIntroMessage found when parsing direct DHT message"); + return false; + } default: llarp::LogWarn("unknown dht message type: ", (char)*strbuf.base); // bad msg type diff --git a/llarp/dht/got_intro.cpp b/llarp/dht/got_intro.cpp index 780ecfead..ce6bc105c 100644 --- a/llarp/dht/got_intro.cpp +++ b/llarp/dht/got_intro.cpp @@ -27,11 +27,12 @@ namespace llarp std::vector< IMessage * > &replies) const { // TODO: implement me better? - auto path = ctx->impl.router->paths.GetLocalPathSet(pathID); - if(path) + auto pathset = ctx->impl.router->paths.GetLocalPathSet(pathID); + if(pathset) { - return path->HandleGotIntroMessage(this); + return pathset->HandleGotIntroMessage(this); } + llarp::LogWarn("No path for got intro message pathid=", pathID); return false; } diff --git a/llarp/dht/publish_intro.cpp b/llarp/dht/publish_intro.cpp index b0c69dcbe..7aa9f3427 100644 --- a/llarp/dht/publish_intro.cpp +++ b/llarp/dht/publish_intro.cpp @@ -27,6 +27,8 @@ namespace llarp if(!bencode_read_integer(val, &S)) return false; } + if(!BEncodeMaybeReadDictInt("T", txID, read, key, val)) + return false; if(!BEncodeMaybeReadDictInt("V", version, read, key, val)) return false; return read; @@ -39,7 +41,7 @@ namespace llarp auto &dht = ctx->impl; if(!I.VerifySignature(&dht.router->crypto)) { - llarp::LogWarn("invalid introset signature"); + llarp::LogWarn("invalid introset signature, ", I); return false; } if(I.W && !I.W->IsValid(dht.router->crypto.shorthash)) @@ -69,6 +71,8 @@ namespace llarp if(!BEncodeWriteDictInt(buf, "S", S)) return false; } + if(!BEncodeWriteDictInt(buf, "T", txID)) + return false; if(!BEncodeWriteDictInt(buf, "V", LLARP_PROTO_VERSION)) return false; return bencode_end(buf); diff --git a/llarp/iwp/frame_state.cpp b/llarp/iwp/frame_state.cpp index 735cd2f11..c7bfaed7a 100644 --- a/llarp/iwp/frame_state.cpp +++ b/llarp/iwp/frame_state.cpp @@ -199,44 +199,36 @@ frame_state::inbound_frame_complete(uint64_t id) " != ", llarp::AlignedBuffer< 32 >(rxmsg->msginfo.hash())); return false; } - if(id == nextMsgID) - { - llarp_link_session *impl = parent; - if(id == 0) + llarp_link_session *impl = parent; + + if(id == 0) + { + success = router->HandleRecvLinkMessage(parent, buf); + if(impl->CheckRCValid()) { - success = router->HandleRecvLinkMessage(parent, buf); - if(impl->CheckRCValid()) - { - if(!impl->IsEstablished()) - { - impl->send_LIM(); - impl->session_established(); - } - ++nextMsgID; - } - else + if(!impl->IsEstablished()) { - llarp::PubKey k = impl->remote_router.pubkey; - llarp::LogWarn("spoofed LIM from ", k); - impl->close(); - success = false; + impl->send_LIM(); + impl->session_established(); } + ++nextMsgID; } else { - recvqueue.Put(new InboundMessage(id, msg)); - success = true; + llarp::PubKey k = impl->remote_router.pubkey; + llarp::LogWarn("spoofed LIM from ", k); + impl->close(); + success = false; } } else { - llarp::LogWarn("out of order message expected ", nextMsgID, " but got ", - id); recvqueue.Put(new InboundMessage(id, msg)); success = true; } } + delete rxmsg; rx.erase(id); @@ -334,10 +326,10 @@ frame_state::next_frame(llarp_buffer_t *buf) llarp::LogDebug("next frame, ", left, " frames left in send queue"); if(left) { - sendbuf_t *send = sendqueue.front(); - buf->base = send->data(); - buf->cur = send->data(); - buf->sz = send->size(); + auto &send = sendqueue.front(); + buf->base = send->data(); + buf->cur = send->data(); + buf->sz = send->size(); return true; } return false; @@ -346,9 +338,9 @@ frame_state::next_frame(llarp_buffer_t *buf) void frame_state::pop_next_frame() { - sendbuf_t *buf = sendqueue.front(); - sendqueue.pop(); + auto &buf = sendqueue.front(); delete buf; + sendqueue.pop(); } void diff --git a/llarp/path.cpp b/llarp/path.cpp index 62bb6f4d6..f48761e8e 100644 --- a/llarp/path.cpp +++ b/llarp/path.cpp @@ -292,6 +292,12 @@ namespace llarp { hops[idx].txID = hops[idx + 1].rxID; } + // initialize parts of the introduction + intro.router = hops[h->numHops - 1].router.pubkey; + // TODO: or is it rxid ? + intro.pathID = hops[h->numHops - 1].txID; + + m_InboundMessageParser.from = RXID(); } void @@ -312,6 +318,12 @@ namespace llarp return hops[0].rxID; } + bool + Path::IsReady() const + { + return intro.latency > 0 && status == ePathEstablished; + } + RouterID Path::Upstream() const { @@ -419,12 +431,15 @@ namespace llarp { if(status == ePathBuilding) { + // finish initializing introduction + intro.expiresAt = buildStarted + hops[0].lifetime; // confirm that we build the path status = ePathEstablished; llarp::LogInfo("path is confirmed tx=", TXID(), " rx=", RXID()); if(m_BuiltHook) m_BuiltHook(this); m_BuiltHook = nullptr; + llarp::routing::PathLatencyMessage latency; latency.T = rand(); m_LastLatencyTestID = latency.T; @@ -442,8 +457,8 @@ namespace llarp { if(msg->L == m_LastLatencyTestID) { - Latency = llarp_time_now_ms() - m_LastLatencyTestTime; - llarp::LogInfo("path latency is ", Latency, " ms for tx=", TXID(), + intro.latency = llarp_time_now_ms() - m_LastLatencyTestTime; + llarp::LogInfo("path latency is ", intro.latency, " ms for tx=", TXID(), " rx=", RXID()); m_LastLatencyTestID = 0; return true; diff --git a/llarp/pathset.cpp b/llarp/pathset.cpp index b9c3abc19..56b0fa76a 100644 --- a/llarp/pathset.cpp +++ b/llarp/pathset.cpp @@ -1,3 +1,5 @@ +#include +#include #include #include @@ -87,10 +89,65 @@ namespace llarp } bool - PathSet::HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg) + PathSet::GetCurrentIntroductions( + std::list< llarp::service::Introduction >& intros) const + { + size_t count = 0; + auto itr = m_Paths.begin(); + while(itr != m_Paths.end()) + { + if(itr->second->IsReady()) + { + intros.push_back(itr->second->intro); + ++count; + } + ++itr; + } + return count > 0; + } + + bool + PathSet::ShouldPublishDescriptors() const { // TODO: implement me - return false; + return m_CurrentPublishTX == 0 || true; + } + + Path* + PathSet::PickRandomEstablishedPath() + { + std::vector< Path* > established; + auto itr = m_Paths.begin(); + while(itr != m_Paths.end()) + { + if(itr->second->IsReady()) + established.push_back(itr->second); + ++itr; + } + auto sz = established.size(); + if(sz) + { + return established[rand() % sz]; + } + else + return nullptr; + } + + bool + PathSet::PublishIntroSet(const llarp::service::IntroSet& introset, + llarp_router* r) + { + auto path = PickRandomEstablishedPath(); + if(path) + { + m_CurrentPublishTX = rand(); + llarp::routing::DHTMessage msg; + msg.M.push_back( + new llarp::dht::PublishIntroMessage(introset, m_CurrentPublishTX)); + return path->SendRoutingMessage(&msg, r); + } + else + return false; } } // namespace path diff --git a/llarp/router.cpp b/llarp/router.cpp index 0d2e54cb4..1f65f06c5 100644 --- a/llarp/router.cpp +++ b/llarp/router.cpp @@ -35,6 +35,7 @@ llarp_router::llarp_router() , dht(llarp_dht_context_new(this)) , inbound_link_msg_parser(this) , explorePool(llarp_pathbuilder_context_new(this, dht)) + , hiddenServiceContext(this) { // set rational defaults @@ -379,6 +380,7 @@ void llarp_router::Tick() { llarp::LogDebug("tick router"); + paths.ExpirePaths(); // TODO: don't do this if we have enough paths already if(inboundLinks.size() == 0) @@ -393,15 +395,9 @@ llarp_router::Tick() llarp::LogWarn("not enough nodes known to build exploritory paths, have ", N, " nodes, need 3 now (will be 5 later)"); } + hiddenServiceContext.Tick(); } paths.TickPaths(); - llarp_link_session_iter iter; - iter.user = this; - iter.visit = &send_padded_message; - if(sendPadding) - { - outboundLink->iter_sessions(iter); - } } bool @@ -1119,29 +1115,12 @@ llarp_router::LoadHiddenServiceConfig(const char *fname) return false; for(const auto &config : conf.services) { - if(!AddHiddenService(config)) + if(!hiddenServiceContext.AddEndpoint(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 diff --git a/llarp/router.hpp b/llarp/router.hpp index 89e71e9cc..89e1bf28a 100644 --- a/llarp/router.hpp +++ b/llarp/router.hpp @@ -94,6 +94,8 @@ struct llarp_router llarp_pathbuilder_select_hop_func selectHopFunc = nullptr; llarp_pathbuilder_context *explorePool = nullptr; + llarp::service::Context hiddenServiceContext; + llarp_link *outboundLink = nullptr; std::list< llarp_link * > inboundLinks; diff --git a/llarp/routing/message_parser.cpp b/llarp/routing/message_parser.cpp index 78f8d6d2a..898481bf2 100644 --- a/llarp/routing/message_parser.cpp +++ b/llarp/routing/message_parser.cpp @@ -73,7 +73,10 @@ namespace llarp firstKey = true; if(bencode_read_dict(&buf, &reader)) { - result = msg->HandleMessage(h, r); + msg->from = from; + result = msg->HandleMessage(h, r); + if(!result) + llarp::LogWarn("Failed to handle inbound routing message"); delete msg; } else diff --git a/llarp/service.cpp b/llarp/service.cpp index f83ee0f26..455d65c51 100644 --- a/llarp/service.cpp +++ b/llarp/service.cpp @@ -1,5 +1,6 @@ #include #include "buffer.hpp" +#include "ini.hpp" #include "router.hpp" namespace llarp @@ -79,18 +80,18 @@ namespace llarp IntroSet::DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) { bool read = false; - if(!BEncodeMaybeReadDictEntry("A", A, read, key, buf)) + if(!BEncodeMaybeReadDictEntry("a", A, read, key, buf)) return false; - if(llarp_buffer_eq(key, "I")) + if(llarp_buffer_eq(key, "i")) { return BEncodeReadList(I, buf); } - if(!BEncodeMaybeReadDictInt("V", version, read, key, buf)) + if(!BEncodeMaybeReadDictInt("v", version, read, key, buf)) return false; - if(!BEncodeMaybeReadDictEntry("Z", Z, read, key, buf)) + if(!BEncodeMaybeReadDictEntry("z", Z, read, key, buf)) return false; return read; @@ -113,11 +114,13 @@ namespace llarp // write version if(!BEncodeWriteDictInt(buf, "v", version)) return false; + /* if(W) { if(!BEncodeWriteDictEntry("w", *W, buf)) return false; } + */ if(!BEncodeWriteDictEntry("z", Z, buf)) return false; @@ -192,6 +195,7 @@ namespace llarp crypto->identity_keygen(signkey); pub.enckey = llarp::seckey_topublic(enckey); pub.signkey = llarp::seckey_topublic(signkey); + pub.vanity.Zero(); } bool @@ -235,48 +239,16 @@ 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); - } - bool Config::Load(const std::string& fname) { // TODO: implement me - return false; + ini::Parser parser(fname); + for(const auto& sec : parser.top().ordered_sections) + { + services.push_back({sec->first, sec->second.values}); + } + return services.size() > 0; } } // namespace service diff --git a/llarp/service/context.cpp b/llarp/service/context.cpp new file mode 100644 index 000000000..95abc5071 --- /dev/null +++ b/llarp/service/context.cpp @@ -0,0 +1,64 @@ +#include + +namespace llarp +{ + namespace service + { + Context::Context(llarp_router *r) : m_Router(r) + { + } + + Context::~Context() + { + auto itr = m_Endpoints.begin(); + while(itr != m_Endpoints.end()) + { + delete itr->second; + itr = m_Endpoints.erase(itr); + } + } + + void + Context::Tick() + { + auto itr = m_Endpoints.begin(); + while(itr != m_Endpoints.end()) + { + itr->second->Tick(); + ++itr; + } + } + + bool + Context::AddEndpoint(const Config::section_t &conf) + { + auto itr = m_Endpoints.find(conf.first); + if(itr != m_Endpoints.end()) + { + llarp::LogError("cannot add hidden service with duplicate name: ", + conf.first); + return false; + } + auto service = new llarp::service::Endpoint(conf.first, m_Router); + for(const auto &option : conf.second) + { + auto &k = option.first; + auto &v = option.second; + if(!service->SetOption(k, v)) + { + delete service; + return false; + } + } + if(service->Start()) + { + llarp::LogInfo("added hidden service endpoint ", conf.first); + m_Endpoints.emplace(conf.first, service); + return true; + } + llarp::LogError("failed to start hidden service endpoint ", conf.first); + delete service; + return false; + } + } +} \ No newline at end of file diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp new file mode 100644 index 000000000..42e318741 --- /dev/null +++ b/llarp/service/endpoint.cpp @@ -0,0 +1,101 @@ +#include +#include "router.hpp" + +namespace llarp +{ + namespace service + { + Endpoint::Endpoint(const std::string& name, llarp_router* r) + : llarp_pathbuilder_context(r, r->dht), m_Router(r), m_Name(name) + { + } + + bool + Endpoint::SetOption(const std::string& k, const std::string& v) + { + if(k == "keyfile") + { + m_Keyfile = v; + return true; + } + return false; + } + + void + Endpoint::Tick() + { + if(ShouldPublishDescriptors()) + { + llarp::LogDebug("publish descriptor for endpoint ", m_Name); + IntroSet introset; + if(!GetCurrentIntroductions(introset.I)) + { + llarp::LogWarn("could not publish descriptors for endpoint ", m_Name, + " because we couldn't get any introductions"); + return; + } + if(!m_Identity.SignIntroSet(introset, &m_Router->crypto)) + { + llarp::LogWarn("failed to sign introset for endpoint ", m_Name); + return; + } + if(PublishIntroSet(introset, m_Router)) + { + llarp::LogInfo("publishing introset for endpoint ", m_Name); + } + else + { + llarp::LogWarn("failed to publish intro set for endpoint ", m_Name); + } + } + } + + bool + Endpoint::HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg) + { + auto crypto = &m_Router->crypto; + for(const auto& introset : msg->I) + { + if(!introset.VerifySignature(crypto)) + { + llarp::LogWarn( + "invalid signature in got intro message for service endpoint ", + m_Name); + return false; + } + if(m_Identity.pub == introset.A) + { + llarp::LogInfo( + "got introset publish confirmation for hidden service endpoint ", + m_Name); + } + else + { + /// TODO: implement lookup response + } + } + return true; + } + + 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() + { + } + } +} \ No newline at end of file