llarp/service/endpoint.hpp
Namespaces
Classes
Defines
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