From 85f9f46362e7bc768728119a74adc3bf51119463 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 29 Nov 2018 08:12:35 -0500 Subject: [PATCH] snode stubs (initial) --- include/llarp/exit/endpoint.hpp | 2 +- include/llarp/exit/session.hpp | 48 ++++++++++++++++++++++++++- include/llarp/handlers/null.hpp | 31 +++++++++++++++++ include/llarp/handlers/tun.hpp | 9 +++-- include/llarp/service/endpoint.hpp | 45 +++++++++++++------------ llarp/exit/endpoint.cpp | 36 ++++++++++---------- llarp/exit/session.cpp | 14 +++++--- llarp/handlers/tun.cpp | 41 +++++++++++++---------- llarp/service/context.cpp | 9 ++--- llarp/service/endpoint.cpp | 53 ++++++++++++++++++++++++++++-- 10 files changed, 217 insertions(+), 71 deletions(-) create mode 100644 include/llarp/handlers/null.hpp diff --git a/include/llarp/exit/endpoint.hpp b/include/llarp/exit/endpoint.hpp index 97ff5fd96..72a76c393 100644 --- a/include/llarp/exit/endpoint.hpp +++ b/include/llarp/exit/endpoint.hpp @@ -19,7 +19,7 @@ namespace llarp struct Endpoint { Endpoint(const llarp::PubKey& remoteIdent, - const llarp::PathID_t& beginPath, bool rewriteDst, huint32_t ip, + const llarp::PathID_t& beginPath, bool rewriteIP, huint32_t ip, llarp::handlers::ExitEndpoint* parent); ~Endpoint(); diff --git a/include/llarp/exit/session.hpp b/include/llarp/exit/session.hpp index 80971d8e5..a8ccbbf13 100644 --- a/include/llarp/exit/session.hpp +++ b/include/llarp/exit/session.hpp @@ -3,20 +3,24 @@ #include #include #include +#include #include namespace llarp { namespace exit { + /// a persisiting exit session with an exit router struct BaseSession : public llarp::path::Builder { + static constexpr size_t MaxUpstreamQueueLength = 256; + BaseSession(const llarp::RouterID& exitRouter, std::function< bool(llarp_buffer_t) > writepkt, llarp_router* r, size_t numpaths, size_t hoplen); - ~BaseSession(); + virtual ~BaseSession(); bool SelectHop(llarp_nodedb* db, const RouterContact& prev, RouterContact& cur, @@ -34,10 +38,16 @@ namespace llarp bool FlushUpstreamTraffic(); + bool + IsReady() const; + protected: llarp::RouterID m_ExitRouter; std::function< bool(llarp_buffer_t) > m_WritePacket; + + virtual void + PopulateRequest(llarp::routing::ObtainExitMessage & msg) const = 0; bool HandleTrafficDrop(llarp::path::Path* p, const llarp::PathID_t& path, @@ -55,6 +65,42 @@ namespace llarp llarp::SecretKey m_ExitIdentity; }; + struct ExitSession final : public BaseSession + { + ExitSession(const llarp::RouterID& snodeRouter, + std::function< bool(llarp_buffer_t) > writepkt, + llarp_router* r, size_t numpaths, size_t hoplen) : BaseSession(snodeRouter, writepkt, r,numpaths, hoplen) {}; + + ~ExitSession() {}; + + protected: + virtual void + PopulateRequest(llarp::routing::ObtainExitMessage & msg) const override + { + // TODO: set expiration time + msg.X = 0; + msg.E = 1; + } + }; + + struct SNodeSession final : public BaseSession + { + SNodeSession(const llarp::RouterID& snodeRouter, + std::function< bool(llarp_buffer_t) > writepkt, + llarp_router* r, size_t numpaths, size_t hoplen) : BaseSession(snodeRouter, writepkt, r,numpaths, hoplen) {}; + + ~SNodeSession() {}; + + protected: + void + PopulateRequest(llarp::routing::ObtainExitMessage & msg) const override + { + // TODO: set expiration time + msg.X = 0; + msg.E = 0; + } + }; + } // namespace exit } // namespace llarp diff --git a/include/llarp/handlers/null.hpp b/include/llarp/handlers/null.hpp new file mode 100644 index 000000000..8a9b45fe6 --- /dev/null +++ b/include/llarp/handlers/null.hpp @@ -0,0 +1,31 @@ +#ifndef LLARP_HANDLERS_NULL_HPP +#define LLARP_HANDLERS_NULL_HPP +#include + +namespace llarp +{ + namespace handlers + { + struct NullEndpoint final : public llarp::service::Endpoint + { + NullEndpoint(const std::string & name, llarp_router *r) : llarp::service::Endpoint(name, r) {}; + + bool HandleWriteIPPacket(llarp_buffer_t, std::function) override + { + return true; + } + + huint32_t ObtainIPForAddr(const byte_t*, bool) override + { + return {0}; + } + + bool HasAddress(const byte_t *) const override + { + return false; + } + }; + } +} + +#endif \ No newline at end of file diff --git a/include/llarp/handlers/tun.hpp b/include/llarp/handlers/tun.hpp index d1b33c0b9..08615c49c 100644 --- a/include/llarp/handlers/tun.hpp +++ b/include/llarp/handlers/tun.hpp @@ -49,7 +49,7 @@ namespace llarp /// overrides Endpoint /// handle inbound traffic bool - ProcessDataMessage(service::ProtocolMessage* msg); + HandleWriteIPPacket(llarp_buffer_t buf, std::function getFromIP) override; /// queue outbound packet to the world bool @@ -109,14 +109,14 @@ namespace llarp } bool - HasAddress(const byte_t* addr) const + HasAddress(const byte_t* addr) const override { return m_AddrToIP.find(addr) != m_AddrToIP.end(); } /// get ip address for key unconditionally huint32_t - ObtainIPForAddr(const byte_t* addr); + ObtainIPForAddr(const byte_t* addr, bool serviceNode) override; protected: using PacketQueue_t = llarp::util::CoDelQueue< @@ -150,6 +150,9 @@ namespace llarp AlignedBuffer< 32 >::Hash > m_AddrToIP; + /// maps key to true if key is a service node, maps key to false if key is a hidden service + std::unordered_map, bool, AlignedBuffer<32>::Hash> m_SNodes; + private: bool QueueInboundPacketForExit(llarp_buffer_t buf) diff --git a/include/llarp/service/endpoint.hpp b/include/llarp/service/endpoint.hpp index a8d622c3c..ff78deb04 100644 --- a/include/llarp/service/endpoint.hpp +++ b/include/llarp/service/endpoint.hpp @@ -110,18 +110,10 @@ namespace llarp HasPathToService(const Address& remote) const; virtual huint32_t - ObtainIPForAddr(const byte_t* addr) - { - (void)addr; - return {0}; - } + ObtainIPForAddr(const byte_t* addr, bool serviceNode) = 0; virtual bool - HasAddress(const byte_t* addr) const - { - (void)addr; - return false; - } + HasAddress(const byte_t* addr) const = 0; /// return true if we have a pending job to build to a hidden service but /// it's not done yet @@ -136,16 +128,11 @@ namespace llarp bool HandleDataMessage(const PathID_t&, ProtocolMessage* msg); - virtual bool - ProcessDataMessage(ProtocolMessage* msg) - { -#ifdef TESTNET - llarp::LogInfo("Got message from ", msg->sender.Addr()); -#else - (void)msg; -#endif - return true; - } + virtual + bool HandleWriteIPPacket(llarp_buffer_t pkt, std::function getFromIP) = 0; + + bool + ProcessDataMessage(ProtocolMessage* msg); bool HandleDataMessage(const PathID_t&); @@ -167,7 +154,10 @@ namespace llarp HandlePathBuilt(path::Path* path); bool - SendToOrQueue(const byte_t* addr, llarp_buffer_t payload, ProtocolType t); + SendToServiceOrQueue(const byte_t* addr, llarp_buffer_t payload, ProtocolType t); + + bool + SendToSNodeOrQueue(const byte_t * addr, llarp_buffer_t payload); struct PendingBuffer { @@ -339,6 +329,15 @@ namespace llarp EnsurePathToService(const Address& remote, PathEnsureHook h, uint64_t timeoutMS, bool lookupOnRandomPath = false); + using SNodeEnsureHook = std::function; + + /// ensure a path to a service node by public key + void + EnsurePathToSNode(const RouterID & remote); + + bool + HasPathToSNode(const RouterID &remote) const; + void PutSenderFor(const ConvoTag& tag, const ServiceInfo& info); @@ -446,6 +445,10 @@ namespace llarp Sessions m_DeadSessions; + using SNodeSessions = std::unordered_multimap, RouterID::Hash>; + + SNodeSessions m_SNodeSessions; + std::unordered_map< Address, ServiceInfo, Address::Hash > m_AddressToService; diff --git a/llarp/exit/endpoint.cpp b/llarp/exit/endpoint.cpp index 665c3efb0..94229349b 100644 --- a/llarp/exit/endpoint.cpp +++ b/llarp/exit/endpoint.cpp @@ -104,31 +104,31 @@ namespace llarp if(!pkt.Load(buf)) return false; - huint32_t src; - if(m_RewriteSource) - src = m_Parent->GetIfAddr(); - else - src = pkt.src(); - pkt.UpdateIPv4PacketOnDst(src, m_IP); + huint32_t src; + if(m_RewriteSource) + src = m_Parent->GetIfAddr(); + else + src = pkt.src(); + pkt.UpdateIPv4PacketOnDst(src, m_IP); - if(m_DownstreamQueue.size() == 0) - m_DownstreamQueue.emplace_back(); - auto pktbuf = pkt.Buffer(); - auto & msg = m_DownstreamQueue.back(); - if(msg.Size() + pktbuf.sz > llarp::routing::ExitPadSize) - { - m_DownstreamQueue.emplace_back(); - return m_DownstreamQueue.back().PutBuffer(pktbuf); - } - else - return msg.PutBuffer(pktbuf); + if(m_DownstreamQueue.size() == 0) + m_DownstreamQueue.emplace_back(); + auto pktbuf = pkt.Buffer(); + auto & msg = m_DownstreamQueue.back(); + if(msg.Size() + pktbuf.sz > llarp::routing::ExitPadSize) + { + m_DownstreamQueue.emplace_back(); + return m_DownstreamQueue.back().PutBuffer(pktbuf); + } + else + return msg.PutBuffer(pktbuf); } bool Endpoint::FlushInboundTraffic() { auto path = GetCurrentPath(); - bool sent = m_DownstreamQueue.size() == 0; + bool sent = m_DownstreamQueue.size() == 0 && path; if(path) { for(auto & msg : m_DownstreamQueue) diff --git a/llarp/exit/session.cpp b/llarp/exit/session.cpp index bfd2570f2..9a8e01493 100644 --- a/llarp/exit/session.cpp +++ b/llarp/exit/session.cpp @@ -56,10 +56,7 @@ namespace llarp llarp::routing::ObtainExitMessage obtain; obtain.S = p->NextSeqNo(); obtain.T = llarp_randint(); - // TODO: set expiratation - obtain.X = 0; - // TODO: distinguish between service node traffic - obtain.E = 1; + PopulateRequest(obtain); if(!obtain.Sign(&router->crypto, m_ExitIdentity)) { llarp::LogError("Failed to sign exit request"); @@ -103,6 +100,9 @@ namespace llarp bool BaseSession::QueueUpstreamTraffic(llarp::net::IPv4Packet pkt, const size_t N) { + // queue overflow + if(m_UpstreamQueue.size() >= MaxUpstreamQueueLength) + return false; if(m_UpstreamQueue.size() == 0) m_UpstreamQueue.emplace_back(); auto & back = m_UpstreamQueue.back(); @@ -117,6 +117,12 @@ namespace llarp return back.PutBuffer(buf); } + bool + BaseSession::IsReady() const + { + return AvailablePaths(llarp::path::ePathRoleExit) > 0; + } + bool BaseSession::FlushUpstreamTraffic() { diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 25dbc1bdb..79dce2863 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -41,7 +41,7 @@ namespace llarp llarp::LogError(Name(), " bad exit router key: ", v); return false; } - m_Exit.reset(new llarp::exit::BaseSession( + m_Exit.reset(new llarp::exit::ExitSession( exitRouter, std::bind(&TunEndpoint::QueueInboundPacketForExit, this, std::placeholders::_1), @@ -344,6 +344,7 @@ namespace llarp TunEndpoint::FlushSend() { m_UserToNetworkPktQueue.Process([&](net::IPv4Packet &pkt) { + std::function sendFunc; auto itr = m_IPToAddr.find(pkt.dst()); if(itr == m_IPToAddr.end()) { @@ -351,21 +352,30 @@ namespace llarp { pkt.UpdateIPv4PacketOnDst({0}, pkt.dst()); m_Exit->QueueUpstreamTraffic(std::move(pkt), llarp::routing::ExitPadSize); + return true; } else + { llarp::LogWarn(Name(), " has no endpoint for ", pkt.dst()); - return true; + return true; + } } + if(m_SNodes.at(itr->second)) + { + sendFunc = std::bind(&TunEndpoint::SendToSNodeOrQueue, this, itr->second.data(), std::placeholders::_1); + } + else + { + sendFunc = std::bind(&TunEndpoint::SendToServiceOrQueue, this, itr->second.data(), std::placeholders::_1, service::eProtocolTraffic); + } // prepare packet for insertion into network // this includes clearing IP addresses, recalculating checksums, etc pkt.UpdateIPv4PacketOnSrc(); - if(!SendToOrQueue(itr->second.data(), pkt.Buffer(), - service::eProtocolTraffic)) - { - llarp::LogWarn(Name(), " did not flush packets"); - } + if(sendFunc && sendFunc(pkt.Buffer())) + return true; + llarp::LogWarn(Name(), " did not flush packets"); return true; }); if(m_Exit) @@ -373,14 +383,13 @@ namespace llarp } bool - TunEndpoint::ProcessDataMessage(service::ProtocolMessage *msg) + TunEndpoint::HandleWriteIPPacket(llarp_buffer_t buf, std::function getFromIP) { // llarp::LogInfo("got packet from ", msg->sender.Addr()); - auto themIP = ObtainIPForAddr(msg->sender.Addr().data()); + auto themIP = getFromIP(); // llarp::LogInfo("themIP ", themIP); auto usIP = m_OurIP; - auto buf = llarp::Buffer(msg->payload); - if(m_NetworkToUserPktQueue.EmplaceIf( + return m_NetworkToUserPktQueue.EmplaceIf( [buf, themIP, usIP](net::IPv4Packet &pkt) -> bool { // load if(!pkt.Load(buf)) @@ -402,11 +411,7 @@ namespace llarp // update packet to use proper addresses, recalc checksums pkt.UpdateIPv4PacketOnDst(themIP, usIP); return true; - })) - - llarp::LogDebug(Name(), " handle data message ", msg->payload.size(), - " bytes from ", themIP); - return true; + }); } huint32_t @@ -416,7 +421,7 @@ namespace llarp } huint32_t - TunEndpoint::ObtainIPForAddr(const byte_t *a) + TunEndpoint::ObtainIPForAddr(const byte_t *a, bool snode) { llarp_time_t now = Now(); huint32_t nextIP = {0}; @@ -443,6 +448,7 @@ namespace llarp { m_AddrToIP[ident] = nextIP; m_IPToAddr[nextIP] = ident; + m_SNodes[ident] = snode; llarp::LogInfo(Name(), " mapped ", ident, " to ", nextIP); MarkIPActive(nextIP); return nextIP; @@ -471,6 +477,7 @@ namespace llarp // remap address m_IPToAddr[oldest.first] = ident; m_AddrToIP[ident] = oldest.first; + m_SNodes[ident] = snode; nextIP = oldest.first; // mark ip active diff --git a/llarp/service/context.cpp b/llarp/service/context.cpp index 45950139e..02e2faa1f 100644 --- a/llarp/service/context.cpp +++ b/llarp/service/context.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include "router.hpp" @@ -107,7 +108,7 @@ namespace llarp { if(itr->second->HasAddress(addr.data())) { - ip = itr->second->ObtainIPForAddr(addr.data()); + ip = itr->second->ObtainIPForAddr(addr.data(), false); return true; } ++itr; @@ -115,7 +116,7 @@ namespace llarp itr = m_Endpoints.find("default"); if(itr != m_Endpoints.end()) { - ip = itr->second->ObtainIPForAddr(addr.data()); + ip = itr->second->ObtainIPForAddr(addr.data(), false); return true; } return false; @@ -151,7 +152,7 @@ namespace llarp llarp::LogError("No tunnel endpoint found"); return zero; } - return tunEndpoint->ObtainIPForAddr(addr.data()); + return tunEndpoint->ObtainIPForAddr(addr.data(), false); } bool @@ -273,7 +274,7 @@ namespace llarp {"null", [](const std::string &nick, llarp_router *r) -> llarp::service::Endpoint * { - return new llarp::service::Endpoint(nick, r); + return new llarp::handlers::NullEndpoint(nick, r); }}}; { diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 64e67404c..198bbf644 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -197,7 +197,7 @@ namespace llarp continue; byte_t tmp[1024] = {0}; auto buf = StackBuffer< decltype(tmp) >(tmp); - if(!SendToOrQueue(introset.A.Addr().data(), buf, eProtocolText)) + if(!SendToServiceOrQueue(introset.A.Addr().data(), buf, eProtocolText)) { llarp::LogWarn(Name(), " failed to send/queue data to ", introset.A.Addr(), " for tag ", tag.ToString()); @@ -783,6 +783,22 @@ namespace llarp return ProcessDataMessage(msg); } + bool + Endpoint::ProcessDataMessage(ProtocolMessage *msg) + { + if(msg->proto == eProtocolTraffic) + { + auto buf = llarp::Buffer(msg->payload); + return HandleWriteIPPacket(buf, std::bind(&Endpoint::ObtainIPForAddr, this, msg->sender.Addr().data(), false)); + } + else if (msg->proto == eProtocolText) + { + // TODO: implement me (?) + return true; + } + return false; + } + bool Endpoint::HandleHiddenServiceFrame(path::Path* p, const ProtocolFrame* frame) @@ -1030,8 +1046,41 @@ namespace llarp && GetPathByRouter(remoteIntro.router) != nullptr; } + void + Endpoint::EnsurePathToSNode(const RouterID & snode) + { + auto range = m_SNodeSessions.equal_range(snode); + if(range.first == range.second) + { + auto themIP = ObtainIPForAddr(snode, true); + m_SNodeSessions.emplace(std::make_pair(snode, std::unique_ptr(new llarp::exit::SNodeSession(snode, std::bind(&Endpoint::HandleWriteIPPacket, this, std::placeholders::_1, [themIP]() -> huint32_t {return themIP;}), m_Router, 2, numHops)))); + } + } + + bool + Endpoint::SendToSNodeOrQueue(const byte_t * addr, llarp_buffer_t buf) + { + llarp::net::IPv4Packet pkt; + if(!pkt.Load(buf)) + return false; + auto range = m_SNodeSessions.equal_range(addr); + auto itr = range.first; + while(itr != range.second) + { + if(itr->second->IsReady()) + { + if(itr->second->QueueUpstreamTraffic(pkt, llarp::routing::ExitPadSize)) + { + return true; + } + } + ++itr; + } + return false; + } + bool - Endpoint::SendToOrQueue(const byte_t* addr, llarp_buffer_t data, + Endpoint::SendToServiceOrQueue(const byte_t* addr, llarp_buffer_t data, ProtocolType t) { service::Address remote(addr);