llarp/service/endpoint.hpp

Namespaces

Name
llarp
[crypto.hpp]
llarp::service

Classes

Name
struct llarp::service::Endpoint

Defines

Name
MIN_SHIFT_INTERVAL

Macros Documentation

define MIN_SHIFT_INTERVAL

#define MIN_SHIFT_INTERVAL 5s

Source code

#pragma once
#include <llarp/dht/messages/gotrouter.hpp>
#include <llarp/ev/ev.hpp>
#include <llarp/exit/session.hpp>
#include <llarp/net/ip_range_map.hpp>
#include <llarp/net/net.hpp>
#include <llarp/path/path.hpp>
#include <llarp/path/pathbuilder.hpp>
#include <llarp/util/compare_ptr.hpp>

// --- begin kitchen sink headers ----
#include <llarp/service/address.hpp>
#include <llarp/service/handler.hpp>
#include <llarp/service/identity.hpp>
#include <llarp/service/pendingbuffer.hpp>
#include <llarp/service/protocol.hpp>
#include <llarp/service/sendcontext.hpp>
#include <llarp/service/protocol_type.hpp>
#include <llarp/service/session.hpp>
#include <llarp/service/lookup.hpp>
#include <llarp/service/endpoint_types.hpp>
#include <llarp/endpoint_base.hpp>
#include <llarp/service/auth.hpp>
// ----- end kitchen sink headers -----

#include <optional>
#include <unordered_map>
#include <variant>
#include <oxenc/variant.h>

#include <llarp/vpn/egres_packet_router.hpp>
#include <llarp/dns/server.hpp>

// minimum time between introset shifts
#ifndef MIN_SHIFT_INTERVAL
#define MIN_SHIFT_INTERVAL 5s
#endif

namespace llarp
{
  namespace service
  {
    struct AsyncKeyExchange;
    struct Context;
    struct EndpointState;
    struct OutboundContext;

    inline constexpr auto IntrosetPublishInterval = path::intro_path_spread / 2;

    inline constexpr auto IntrosetPublishRetryCooldown = 1s;

    inline constexpr auto IntrosetLookupCooldown = 250ms;

    inline constexpr size_t MIN_ENDPOINTS_FOR_LNS_LOOKUP = 2;

    struct Endpoint : public path::Builder,
                      public ILookupHolder,
                      public IDataHandler,
                      public EndpointBase
    {
      Endpoint(AbstractRouter* r, Context* parent);
      ~Endpoint() override;

      bool
      IsReady() const;

      void
      QueueRecvData(RecvDataEvent ev) override;

      bool
      IntrosetIsStale() const;

      virtual std::unordered_map<std::string, std::string>
      NotifyParams() const;

      void
      SetHandler(IDataHandler* h);

      virtual bool
      Configure(const NetworkConfig& conf, const DnsConfig& dnsConf);

      void
      Tick(llarp_time_t now) override;

      virtual bool
      HasIfAddr() const
      {
        return false;
      }

      virtual std::string
      GetIfName() const = 0;

      std::optional<ConvoTag>
      GetBestConvoTagFor(std::variant<Address, RouterID> addr) const override;

      virtual net::ipv6addr_t
      GetIfAddr() const
      {
        return {0};
      }

      virtual std::optional<net::TrafficPolicy>
      GetExitPolicy() const
      {
        return std::nullopt;
      };

      virtual std::set<IPRange>
      GetOwnedRanges() const
      {
        return {};
      };

      virtual void
      Thaw(){};

      void
      ResetInternalState() override;

      const EventLoop_ptr&
      Loop() override;

      AbstractRouter*
      Router();

      virtual bool
      LoadKeyFile();

      virtual bool
      Start();

      std::string
      Name() const override;

      AddressVariant_t
      LocalAddress() const override;

      std::optional<SendStat>
      GetStatFor(AddressVariant_t remote) const override;

      std::unordered_set<AddressVariant_t>
      AllRemoteEndpoints() const override;

      bool
      ShouldPublishDescriptors(llarp_time_t now) const override;

      void
      SRVRecordsChanged() override;

      void
      HandlePathDied(path::Path_ptr p) override;

      virtual vpn::EgresPacketRouter*
      EgresPacketRouter()
      {
        return nullptr;
      };

      virtual vpn::NetworkInterface*
      GetVPNInterface()
      {
        return nullptr;
      }

      bool
      PublishIntroSet(const EncryptedIntroSet& i, AbstractRouter* r) override;

      bool
      PublishIntroSetVia(
          const EncryptedIntroSet& i, AbstractRouter* r, path::Path_ptr p, uint64_t relayOrder);

      bool
      HandleGotIntroMessage(std::shared_ptr<const dht::GotIntroMessage> msg) override;

      bool
      HandleGotRouterMessage(std::shared_ptr<const dht::GotRouterMessage> msg) override;

      bool
      HandleGotNameMessage(std::shared_ptr<const dht::GotNameMessage> msg) override;

      bool
      HandleHiddenServiceFrame(path::Path_ptr p, const service::ProtocolFrame& msg);

      void
      SetEndpointAuth(std::shared_ptr<IAuthPolicy> policy);

      void
      SetAuthInfoForEndpoint(Address remote, AuthInfo info);

      virtual net::ipv6addr_t ObtainIPForAddr(std::variant<Address, RouterID>) = 0;

      virtual std::optional<std::variant<service::Address, RouterID>>
      ObtainAddrForIP(net::ipv6addr_t ip) const = 0;

      // virtual bool
      // HasServiceAddress(const AlignedBuffer< 32 >& addr) const = 0;

      bool
      HasPendingPathToService(const Address& remote) const;

      bool
      HandleDataMessage(
          path::Path_ptr path, const PathID_t from, std::shared_ptr<ProtocolMessage> msg) override;

      virtual bool
      HandleInboundPacket(
          const ConvoTag tag, const llarp_buffer_t& pkt, ProtocolType t, uint64_t seqno) = 0;

      // virtual bool
      // HandleWriteIPPacket(const llarp_buffer_t& pkt,
      //                    std::function< huint128_t(void) > getFromIP) = 0;

      bool
      ProcessDataMessage(std::shared_ptr<ProtocolMessage> msg);

      void
      EnsureRouterIsKnown(const RouterID& router);

      bool
      LookupRouterAnon(RouterID router, RouterLookupHandler handler);

      void
      LookupNameAsync(
          std::string name,
          std::function<void(std::optional<std::variant<Address, RouterID>>)> resultHandler)
          override;

      void
      LookupServiceAsync(
          std::string name,
          std::string service,
          std::function<void(std::vector<dns::SRVData>)> resultHandler) override;

      virtual void
      Pump(llarp_time_t now);

      bool
      Stop() override;

      const Identity&
      GetIdentity() const
      {
        return m_Identity;
      }

      void
      MapExitRange(IPRange range, service::Address exit);

      void
      UnmapExitRange(IPRange range);

      void
      UnmapRangeByExit(IPRange range, std::string exit);

      void
      map_exit(
          std::string name,
          std::string token,
          std::vector<IPRange> ranges,
          std::function<void(bool, std::string)> result);

      void
      PutLookup(IServiceLookup* lookup, uint64_t txid) override;

      void
      HandlePathBuilt(path::Path_ptr path) override;

      bool
      HandleDataDrop(path::Path_ptr p, const PathID_t& dst, uint64_t s);

      bool
      CheckPathIsDead(path::Path_ptr p, llarp_time_t latency);

      using PendingBufferQueue = std::deque<PendingBuffer>;

      size_t
      RemoveAllConvoTagsFor(service::Address remote);

      bool
      WantsOutboundSession(const Address&) const override;

      void MarkAddressOutbound(AddressVariant_t) override;

      bool
      ShouldBundleRC() const override
      {
        return false;
      }

      void
      BlacklistSNode(const RouterID snode) override;

      std::optional<std::variant<Address, RouterID>>
      GetEndpointWithConvoTag(ConvoTag t) const override;

      bool
      HasConvoTag(const ConvoTag& t) const override;

      bool
      ShouldBuildMore(llarp_time_t now) const override;

      virtual llarp_time_t
      PathAlignmentTimeout() const
      {
        constexpr auto DefaultPathAlignmentTimeout = 30s;
        return DefaultPathAlignmentTimeout;
      }

      bool
      EnsurePathTo(
          std::variant<Address, RouterID> addr,
          std::function<void(std::optional<ConvoTag>)> hook,
          llarp_time_t timeout) override;

      // passed a sendto context when we have a path established otherwise
      // nullptr if the path was not made before the timeout
      using PathEnsureHook = std::function<void(Address, OutboundContext*)>;

      static constexpr auto DefaultPathEnsureTimeout = 2s;

      bool
      EnsurePathToService(
          const Address remote,
          PathEnsureHook h,
          llarp_time_t timeoutMS = DefaultPathEnsureTimeout);

      using SNodeEnsureHook = std::function<void(const RouterID, exit::BaseSession_ptr, ConvoTag)>;

      void
      InformPathToService(const Address remote, OutboundContext* ctx);

      bool
      EnsurePathToSNode(const RouterID remote, SNodeEnsureHook h);

      bool
      HasPendingRouterLookup(const RouterID remote) const;

      bool
      HasPathToSNode(const RouterID remote) const;

      bool
      HasFlowToService(const Address remote) const;

      void
      PutSenderFor(const ConvoTag& tag, const ServiceInfo& info, bool inbound) override;

      bool
      HasInboundConvo(const Address& addr) const override;

      bool
      HasOutboundConvo(const Address& addr) const override;

      bool
      GetCachedSessionKeyFor(const ConvoTag& remote, SharedSecret& secret) const override;
      void
      PutCachedSessionKeyFor(const ConvoTag& remote, const SharedSecret& secret) override;

      bool
      GetSenderFor(const ConvoTag& remote, ServiceInfo& si) const override;

      void
      PutIntroFor(const ConvoTag& remote, const Introduction& intro) override;

      bool
      GetIntroFor(const ConvoTag& remote, Introduction& intro) const override;

      void
      RemoveConvoTag(const ConvoTag& remote) override;

      void
      ConvoTagTX(const ConvoTag& remote) override;

      void
      ConvoTagRX(const ConvoTag& remote) override;

      void
      PutReplyIntroFor(const ConvoTag& remote, const Introduction& intro) override;

      bool
      GetReplyIntroFor(const ConvoTag& remote, Introduction& intro) const override;

      bool
      GetConvoTagsForService(const Address& si, std::set<ConvoTag>& tag) const override;

      void
      PutNewOutboundContext(const IntroSet& introset, llarp_time_t timeLeftToAlign);

      std::optional<uint64_t>
      GetSeqNoForConvo(const ConvoTag& tag);

      size_t
      UniqueEndpoints() const;

      bool
      HasExit() const;

      std::optional<std::vector<RouterContact>>
      GetHopsForBuild() override;

      std::optional<std::vector<RouterContact>>
      GetHopsForBuildWithEndpoint(RouterID endpoint);

      virtual void
      PathBuildStarted(path::Path_ptr path) override;

      virtual void
      IntroSetPublishFail();
      virtual void
      IntroSetPublished();

      void
      AsyncProcessAuthMessage(
          std::shared_ptr<ProtocolMessage> msg, std::function<void(AuthResult)> hook);

      void
      SendAuthResult(path::Path_ptr path, PathID_t replyPath, ConvoTag tag, AuthResult st);

      uint64_t
      GenTXID();

      void
      ResetConvoTag(ConvoTag tag, path::Path_ptr path, PathID_t from);

      const std::set<RouterID>&
      SnodeBlacklist() const;

      // Looks up the ConvoTag and, if it exists, calls SendToOrQueue to send it to a remote client
      // or a snode (or nothing, if the convo tag is unknown).
      bool
      SendToOrQueue(ConvoTag tag, const llarp_buffer_t& payload, ProtocolType t) override;

      // Send a to (or queues for sending) to either an address or router id
      bool
      SendToOrQueue(
          const std::variant<Address, RouterID>& addr,
          const llarp_buffer_t& payload,
          ProtocolType t);

      // Sends to (or queues for sending) to a remote client
      bool
      SendToOrQueue(const Address& addr, const llarp_buffer_t& payload, ProtocolType t);

      // Sends to (or queues for sending) to a router
      bool
      SendToOrQueue(const RouterID& addr, const llarp_buffer_t& payload, ProtocolType t);

      std::optional<AuthInfo>
      MaybeGetAuthInfoForEndpoint(service::Address addr);

     protected:
      Context* const context;

      virtual bool
      SupportsV6() const = 0;

      void
      RegenAndPublishIntroSet();

      IServiceLookup*
      GenerateLookupByTag(const Tag& tag);

      void
      PrefetchServicesByTag(const Tag& tag);

     private:
      void
      HandleVerifyGotRouter(dht::GotRouterMessage_constptr msg, RouterID id, bool valid);

      bool
      OnLookup(
          const service::Address& addr,
          std::optional<IntroSet> i,
          const RouterID& endpoint,
          llarp_time_t timeLeft,
          uint64_t relayOrder);

      bool
      DoNetworkIsolation(bool failed);

      virtual bool
      SetupNetworking()
      {
        // XXX: override me
        return true;
      }

      virtual bool
      IsolationFailed()
      {
        // XXX: override me
        return false;
      }

      bool
      ReadyForNetwork() const;

     protected:
      bool
      ReadyToDoLookup(size_t num_paths) const;
      path::Path::UniqueEndpointSet_t
      GetUniqueEndpointsForLookup() const;

      IDataHandler* m_DataHandler = nullptr;
      Identity m_Identity;
      net::IPRangeMap<service::Address> m_ExitMap;
      bool m_PublishIntroSet = true;
      std::unique_ptr<EndpointState> m_state;
      std::shared_ptr<IAuthPolicy> m_AuthPolicy;
      std::unordered_map<Address, AuthInfo> m_RemoteAuthInfos;

      std::unordered_map<std::string, std::pair<std::optional<IPRange>, std::optional<AuthInfo>>>
          m_StartupLNSMappings;

      RecvPacketQueue_t m_InboundTrafficQueue;

     public:
      SendMessageQueue_t m_SendQueue;

     private:
      llarp_time_t m_LastIntrosetRegenAttempt = 0s;

     protected:
      void
      FlushRecvData();

      friend struct EndpointUtil;

      // clang-format off
      const IntroSet& introSet() const;
      IntroSet&       introSet();

      using ConvoMap = std::unordered_map<ConvoTag, Session>;
      const ConvoMap& Sessions() const;
      ConvoMap&       Sessions();
      // clang-format on
      thread::Queue<RecvDataEvent> m_RecvQueue;

      util::DecayingHashSet<Address> m_IntrosetLookupFilter;

     private:
      std::shared_ptr<EventLoopWakeup> m_RecvQueueFlusher;
    };

    using Endpoint_ptr = std::shared_ptr<Endpoint>;

  }  // namespace service
}  // namespace llarp

Updated on 2026-01-10 at 22:49:45 +0000