llarp/link/server.hpp

Namespaces

Name
llarp
[crypto.hpp]

Classes

Name
struct llarp::ILinkLayer

Source code

#pragma once

#include <llarp/crypto/types.hpp>
#include <llarp/ev/ev.hpp>
#include "session.hpp"
#include <llarp/net/sock_addr.hpp>
#include <llarp/router_contact.hpp>
#include <llarp/util/thread/threading.hpp>
#include <llarp/config/key_manager.hpp>

#include <list>
#include <memory>
#include <unordered_map>

namespace llarp
{
  using LinkMessageHandler = std::function<bool(ILinkSession*, const llarp_buffer_t&)>;

  using SignBufferFunc = std::function<bool(Signature&, const llarp_buffer_t&)>;

  using TimeoutHandler = std::function<void(ILinkSession*)>;

  using GetRCFunc = std::function<const llarp::RouterContact&(void)>;

  using SessionEstablishedHandler = std::function<bool(ILinkSession*, bool)>;

  using SessionRenegotiateHandler = std::function<bool(llarp::RouterContact, llarp::RouterContact)>;

  using SessionClosedHandler = std::function<void(llarp::RouterID)>;

  using PumpDoneHandler = std::function<void(void)>;

  using Work_t = std::function<void(void)>;
  using WorkerFunc_t = std::function<void(Work_t)>;

  using BeforeConnectFunc_t = std::function<void(llarp::RouterContact)>;

  struct ILinkLayer
  {
    ILinkLayer(
        std::shared_ptr<KeyManager> keyManager,
        EventLoop_ptr evloop,
        GetRCFunc getrc,
        LinkMessageHandler handler,
        SignBufferFunc signFunc,
        BeforeConnectFunc_t before,
        SessionEstablishedHandler sessionEstablish,
        SessionRenegotiateHandler renegotiate,
        TimeoutHandler timeout,
        SessionClosedHandler closed,
        PumpDoneHandler pumpDone,
        WorkerFunc_t doWork);
    virtual ~ILinkLayer() = default;

    llarp_time_t
    Now() const;

    bool
    HasSessionTo(const RouterID& pk);

    void
    ForEachSession(std::function<void(const ILinkSession*)> visit, bool randomize = false) const
        EXCLUDES(m_AuthedLinksMutex);

    void
    ForEachSession(std::function<void(ILinkSession*)> visit) EXCLUDES(m_AuthedLinksMutex);

    void
    UnmapAddr(const SockAddr& addr);

    void
    SendTo_LL(const SockAddr& to, const llarp_buffer_t& pkt);

    void
    Bind(AbstractRouter* router, SockAddr addr);

    virtual std::shared_ptr<ILinkSession>
    NewOutboundSession(const RouterContact& rc, const AddressInfo& ai) = 0;

    std::shared_ptr<ILinkSession>
    FindSessionByPubkey(RouterID pk);

    virtual void
    Pump();

    virtual void
    RecvFrom(const SockAddr& from, ILinkSession::Packet_t pkt) = 0;

    bool
    PickAddress(const RouterContact& rc, AddressInfo& picked) const;

    bool
    TryEstablishTo(RouterContact rc);

    bool
    Start();

    virtual void
    Stop();

    virtual std::string_view
    Name() const = 0;

    void
    CloseSessionTo(const RouterID& remote);

    void
    KeepAliveSessionTo(const RouterID& remote);

    virtual bool
    SendTo(
        const RouterID& remote,
        const llarp_buffer_t& buf,
        ILinkSession::CompletionHandler completed,
        uint16_t priority);

    virtual bool
    GetOurAddressInfo(AddressInfo& addr) const;

    bool
    VisitSessionByPubkey(const RouterID& pk, std::function<bool(ILinkSession*)> visit)
        EXCLUDES(m_AuthedLinksMutex);

    virtual uint16_t
    Rank() const = 0;

    const byte_t*
    TransportPubKey() const;

    const SecretKey&
    RouterEncryptionSecret() const
    {
      return m_RouterEncSecret;
    }

    const SecretKey&
    TransportSecretKey() const;

    bool
    IsCompatable(const llarp::RouterContact& other) const
    {
      const auto us = Name();
      for (const auto& ai : other.addrs)
        if (ai.dialect == us)
          return true;
      return false;
    }

    bool
    MapAddr(const RouterID& pk, ILinkSession* s);

    void
    Tick(llarp_time_t now);

    LinkMessageHandler HandleMessage;
    TimeoutHandler HandleTimeout;
    SignBufferFunc Sign;
    GetRCFunc GetOurRC;
    BeforeConnectFunc_t BeforeConnect;
    SessionEstablishedHandler SessionEstablished;
    SessionClosedHandler SessionClosed;
    SessionRenegotiateHandler SessionRenegotiate;
    PumpDoneHandler PumpDone;
    std::shared_ptr<KeyManager> keyManager;
    WorkerFunc_t QueueWork;

    bool
    operator<(const ILinkLayer& other) const
    {
      auto rankA = Rank(), rankB = other.Rank();
      auto nameA = Name(), nameB = other.Name();
      return std::tie(rankA, nameA, m_ourAddr) < std::tie(rankB, nameB, other.m_ourAddr);
    }

    // void
    // RemovePending(ILinkSession* s) EXCLUDES(m_PendingMutex);

    size_t
    NumberOfPendingSessions() const
    {
      Lock_t lock(m_PendingMutex);
      return m_Pending.size();
    }

    // Returns the file description of the UDP server, if available.
    std::optional<int>
    GetUDPFD() const;

    // Gets a pointer to the router owning us.
    AbstractRouter*
    Router() const
    {
      return m_Router;
    }

    const SockAddr&
    LocalSocketAddr() const
    {
      return m_ourAddr;
    }

    void
    TriggerPump();

   private:
    const SecretKey& m_RouterEncSecret;

   protected:
#ifdef TRACY_ENABLE
    using Lock_t = std::lock_guard<LockableBase(std::mutex)>;
    using Mutex_t = std::mutex;
#else
    using Lock_t = util::NullLock;
    using Mutex_t = util::NullMutex;
#endif
    bool
    PutSession(const std::shared_ptr<ILinkSession>& s);

    AbstractRouter* m_Router;
    SockAddr m_ourAddr;
    std::shared_ptr<llarp::UDPHandle> m_udp;
    SecretKey m_SecretKey;

    using AuthedLinks = std::unordered_multimap<RouterID, std::shared_ptr<ILinkSession>>;
    using Pending = std::unordered_map<SockAddr, std::shared_ptr<ILinkSession>>;
    mutable DECLARE_LOCK(Mutex_t, m_AuthedLinksMutex, ACQUIRED_BEFORE(m_PendingMutex));
    AuthedLinks m_AuthedLinks GUARDED_BY(m_AuthedLinksMutex);
    mutable DECLARE_LOCK(Mutex_t, m_PendingMutex, ACQUIRED_AFTER(m_AuthedLinksMutex));
    Pending m_Pending GUARDED_BY(m_PendingMutex);
    std::unordered_map<SockAddr, RouterID> m_AuthedAddrs;
    std::unordered_map<SockAddr, llarp_time_t> m_RecentlyClosed;

   private:
    std::shared_ptr<int> m_repeater_keepalive;
    std::shared_ptr<EventLoopWakeup> m_Pumper;
  };

  using LinkLayer_ptr = std::shared_ptr<ILinkLayer>;
}  // namespace llarp

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