llarp/path/transit_hop.hpp

Namespaces

Name
llarp
[crypto.hpp]
llarp::dht
llarp::path
std
STL namespace.

Classes

Name
struct llarp::path::TransitHopInfo
class llarp::path::TransitWorker
struct llarp::path::TransitHop

Source code

#pragma once

#include <llarp/constants/path.hpp>
#include <llarp/path/ihophandler.hpp>
#include <llarp/path/path_types.hpp>
#include <llarp/routing/handler.hpp>
#include <llarp/router_id.hpp>
#include <llarp/util/compare_ptr.hpp>
#include <llarp/util/thread/queue.hpp>

namespace llarp
{
  struct LR_CommitRecord;

  namespace dht
  {
    struct GotIntroMessage;
  }

  namespace path
  {
    struct TransitHopInfo
    {
      TransitHopInfo() = default;
      TransitHopInfo(const RouterID& down, const LR_CommitRecord& record);

      PathID_t txID{}, rxID{};
      RouterID upstream{}, downstream{};

      std::string
      ToString() const;
    };

    inline bool
    operator==(const TransitHopInfo& lhs, const TransitHopInfo& rhs)
    {
      return std::tie(lhs.txID, lhs.rxID, lhs.upstream, lhs.downstream)
          == std::tie(rhs.txID, rhs.rxID, rhs.upstream, rhs.downstream);
    }

    inline bool
    operator!=(const TransitHopInfo& lhs, const TransitHopInfo& rhs)
    {
      return !(lhs == rhs);
    }

    inline bool
    operator<(const TransitHopInfo& lhs, const TransitHopInfo& rhs)
    {
      return std::tie(lhs.txID, lhs.rxID, lhs.upstream, lhs.downstream)
          < std::tie(rhs.txID, rhs.rxID, rhs.upstream, rhs.downstream);
    }

    struct PathContext;
    struct TransitHop;

    class TransitWorker
    {
      using Hop_ptr = std::weak_ptr<TransitHop>;
      using Traffic_t = IHopHandler::TrafficEvent_t;

      static constexpr size_t queue_length = 128;

      thread::Queue<std::pair<Hop_ptr, Traffic_t>> m_UpstreamSubmit;
      thread::Queue<std::pair<Hop_ptr, RelayUpstreamMessage>> m_UpstreamGather;
      thread::Queue<std::pair<Hop_ptr, Traffic_t>> m_DownstreamSubmit;
      thread::Queue<std::pair<Hop_ptr, RelayDownstreamMessage>> m_DownstreamGather;
      std::vector<std::jthread> m_Threads;
      std::shared_ptr<EventLoopWakeup> m_Wakeup;
      PathContext& m_PathContext;

      void
      RunUpstream();

      void
      RunDownstream();

      void
      Gather();

     public:
      explicit TransitWorker(PathContext& ctx, const EventLoop_ptr&);
      ~TransitWorker();

      void
      Start(size_t upstream_threads, size_t downstream_threads);
      void
      SubmitUpstream(std::weak_ptr<TransitHop> hop, IHopHandler::TrafficEvent_t ev);
      void
      SubmitDownstream(std::weak_ptr<TransitHop> hop, IHopHandler::TrafficEvent_t ev);
    };

    struct TransitHop : IHopHandler,
                        routing::IMessageHandler,
                        std::enable_shared_from_this<TransitHop>
    {
      friend TransitWorker;
      TransitHop();

      TransitHopInfo info{};
      SharedSecret pathKey{};
      ShortHash nonceXOR{};
      llarp_time_t started = 0s;
      // 10 minutes default
      llarp_time_t lifetime = default_lifetime;
      llarp_proto_version_t version;
      llarp_time_t m_LastActivity = 0s;

      PathID_t
      RXID() const override
      {
        return info.rxID;
      }

      void
      Stop();

      bool destroy = false;

      bool
      operator<(const TransitHop& other) const
      {
        return info < other.info;
      }

      bool
      IsEndpoint(const RouterID& us) const
      {
        return info.upstream == us;
      }

      llarp_time_t
      ExpireTime() const;

      llarp_time_t
      LastRemoteActivityAt() const override
      {
        return m_LastActivity;
      }

      bool
      HandleLRSM(
          uint64_t status, std::array<EncryptedFrame, 8>& frames, AbstractRouter* r) override;

      std::string
      ToString() const;

      bool
      Expired(llarp_time_t now) const override;

      bool
      ExpiresSoon(llarp_time_t now, llarp_time_t dlt) const override
      {
        return now >= ExpireTime() - dlt;
      }

      // send routing message when end of path
      bool
      SendRoutingMessage(const routing::IMessage& msg, AbstractRouter* r) override;

      // handle routing message when end of path
      bool
      HandleRoutingMessage(const routing::IMessage& msg, AbstractRouter* r);

      bool
      HandleDataDiscardMessage(const routing::DataDiscardMessage& msg, AbstractRouter* r) override;

      bool
      HandlePathConfirmMessage(AbstractRouter* r);

      bool
      HandlePathConfirmMessage(const routing::PathConfirmMessage& msg, AbstractRouter* r) override;
      bool
      HandlePathTransferMessage(
          const routing::PathTransferMessage& msg, AbstractRouter* r) override;
      bool
      HandlePathLatencyMessage(const routing::PathLatencyMessage& msg, AbstractRouter* r) override;

      bool
      HandleObtainExitMessage(const routing::ObtainExitMessage& msg, AbstractRouter* r) override;

      bool
      HandleUpdateExitVerifyMessage(
          const routing::UpdateExitVerifyMessage& msg, AbstractRouter* r) override;

      bool
      HandleTransferTrafficMessage(
          const routing::TransferTrafficMessage& msg, AbstractRouter* r) override;

      bool
      HandleUpdateExitMessage(const routing::UpdateExitMessage& msg, AbstractRouter* r) override;

      bool
      HandleGrantExitMessage(const routing::GrantExitMessage& msg, AbstractRouter* r) override;
      bool
      HandleRejectExitMessage(const routing::RejectExitMessage& msg, AbstractRouter* r) override;

      bool
      HandleCloseExitMessage(const routing::CloseExitMessage& msg, AbstractRouter* r) override;

      bool
      HandleHiddenServiceFrame(const service::ProtocolFrame& /*frame*/) override
      {
        LogWarn("Got hidden service data on transit hop");
        return false;
      }

      bool
      HandleGotIntroMessage(const dht::GotIntroMessage& msg);

      bool
      HandleDHTMessage(const dht::IMessage& msg, AbstractRouter* r) override;

      void
      QueueDestroySelf(AbstractRouter* r);

      bool
      HandleUpstream(const llarp_buffer_t& X, const TunnelNonce& Y, AbstractRouter* r) override;
      bool
      HandleDownstream(const llarp_buffer_t& X, const TunnelNonce& Y, AbstractRouter* r) override;

     protected:
      void
      HandleAllUpstream(std::vector<RelayUpstreamMessage> msgs, AbstractRouter* r) override;

      void
      HandleAllDownstream(std::vector<RelayDownstreamMessage> msgs, AbstractRouter* r) override;

     private:
      void
      SetSelfDestruct();
    };
  }  // namespace path

  template <>
  constexpr inline bool IsToStringFormattable<path::TransitHop> = true;
  template <>
  constexpr inline bool IsToStringFormattable<path::TransitHopInfo> = true;

}  // namespace llarp

namespace std
{
  template <>
  struct hash<llarp::path::TransitHopInfo>
  {
    std::size_t
    operator()(llarp::path::TransitHopInfo const& a) const
    {
      hash<llarp::RouterID> RHash{};
      hash<llarp::PathID_t> PHash{};
      return RHash(a.upstream) ^ RHash(a.downstream) ^ PHash(a.txID) ^ PHash(a.rxID);
    }
  };
}  // namespace std

Updated on 2026-04-01 at 23:35:40 +0000