2018-07-09 17:32:11 +00:00
|
|
|
#ifndef LLARP_SERVICE_ENDPOINT_HPP
|
|
|
|
#define LLARP_SERVICE_ENDPOINT_HPP
|
2018-07-19 04:58:39 +00:00
|
|
|
#include <llarp/codel.hpp>
|
2018-07-09 17:32:11 +00:00
|
|
|
#include <llarp/pathbuilder.hpp>
|
|
|
|
#include <llarp/service/Identity.hpp>
|
2018-08-08 19:37:33 +00:00
|
|
|
#include <llarp/service/handler.hpp>
|
2018-07-19 04:58:39 +00:00
|
|
|
#include <llarp/service/protocol.hpp>
|
2018-07-09 17:32:11 +00:00
|
|
|
|
|
|
|
namespace llarp
|
|
|
|
{
|
|
|
|
namespace service
|
|
|
|
{
|
2018-08-09 19:02:17 +00:00
|
|
|
struct Endpoint : public llarp_pathbuilder_context,
|
|
|
|
public ILookupHolder,
|
|
|
|
public IDataHandler
|
2018-07-09 17:32:11 +00:00
|
|
|
{
|
2018-07-18 03:10:21 +00:00
|
|
|
/// minimum interval for publishing introsets
|
|
|
|
static const llarp_time_t INTROSET_PUBLISH_INTERVAL =
|
|
|
|
DEFAULT_PATH_LIFETIME / 4;
|
|
|
|
|
|
|
|
static const llarp_time_t INTROSET_PUBLISH_RETRY_INTERVAL = 5000;
|
|
|
|
|
2018-07-09 17:32:11 +00:00
|
|
|
Endpoint(const std::string& nickname, llarp_router* r);
|
|
|
|
~Endpoint();
|
|
|
|
|
2018-08-08 19:37:33 +00:00
|
|
|
void
|
|
|
|
SetHandler(IDataHandler* h);
|
|
|
|
|
2018-08-16 14:34:15 +00:00
|
|
|
virtual bool
|
2018-07-09 17:32:11 +00:00
|
|
|
SetOption(const std::string& k, const std::string& v);
|
|
|
|
|
2018-08-16 14:34:15 +00:00
|
|
|
virtual void
|
2018-07-18 22:50:05 +00:00
|
|
|
Tick(llarp_time_t now);
|
2018-07-11 16:11:19 +00:00
|
|
|
|
2018-08-09 19:02:17 +00:00
|
|
|
/// router's logic
|
2018-07-19 04:58:39 +00:00
|
|
|
llarp_logic*
|
2018-08-09 19:02:17 +00:00
|
|
|
RouterLogic();
|
|
|
|
|
|
|
|
/// endpoint's logic
|
|
|
|
llarp_logic*
|
|
|
|
EndpointLogic();
|
2018-07-19 04:58:39 +00:00
|
|
|
|
2018-08-17 19:49:58 +00:00
|
|
|
/// endpoint's net loop for sending data to user
|
|
|
|
llarp_ev_loop*
|
|
|
|
EndpointNetLoop();
|
|
|
|
|
2018-07-19 04:58:39 +00:00
|
|
|
llarp_crypto*
|
|
|
|
Crypto();
|
|
|
|
|
|
|
|
llarp_threadpool*
|
|
|
|
Worker();
|
|
|
|
|
2018-07-22 23:14:29 +00:00
|
|
|
llarp_router*
|
|
|
|
Router()
|
|
|
|
{
|
|
|
|
return m_Router;
|
|
|
|
}
|
|
|
|
|
2018-08-16 14:34:15 +00:00
|
|
|
virtual bool
|
2018-07-09 17:32:11 +00:00
|
|
|
Start();
|
|
|
|
|
2018-08-16 14:34:15 +00:00
|
|
|
virtual bool
|
|
|
|
Stop()
|
|
|
|
{
|
|
|
|
// TODO: implement me
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-07-16 03:32:13 +00:00
|
|
|
std::string
|
|
|
|
Name() const;
|
|
|
|
|
2018-07-18 03:10:21 +00:00
|
|
|
bool
|
2018-07-18 22:50:05 +00:00
|
|
|
ShouldPublishDescriptors(llarp_time_t now) const;
|
2018-07-18 03:10:21 +00:00
|
|
|
|
|
|
|
bool
|
|
|
|
PublishIntroSet(llarp_router* r);
|
|
|
|
|
2018-07-11 16:11:19 +00:00
|
|
|
bool
|
|
|
|
HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg);
|
|
|
|
|
2018-08-10 21:34:11 +00:00
|
|
|
bool
|
|
|
|
HandleGotRouterMessage(const llarp::dht::GotRouterMessage* msg);
|
|
|
|
|
2018-07-12 18:21:44 +00:00
|
|
|
bool
|
2018-07-23 07:38:29 +00:00
|
|
|
HandleHiddenServiceFrame(const llarp::service::ProtocolFrame* msg);
|
2018-07-12 18:21:44 +00:00
|
|
|
|
|
|
|
/// return true if we have an established path to a hidden service
|
|
|
|
bool
|
|
|
|
HasPathToService(const Address& remote) const;
|
|
|
|
|
2018-08-10 03:51:38 +00:00
|
|
|
/// return true if we have a pending job to build to a hidden service but
|
|
|
|
/// it's not done yet
|
|
|
|
bool
|
|
|
|
HasPendingPathToService(const Address& remote) const;
|
|
|
|
|
2018-07-12 18:21:44 +00:00
|
|
|
/// return false if we don't have a path to the service
|
|
|
|
/// return true if we did and we removed it
|
|
|
|
bool
|
|
|
|
ForgetPathToService(const Address& remote);
|
|
|
|
|
2018-08-09 19:02:17 +00:00
|
|
|
virtual void
|
|
|
|
HandleDataMessage(ProtocolMessage* msg)
|
|
|
|
{
|
|
|
|
// override me in subclass
|
|
|
|
}
|
|
|
|
|
2018-08-10 21:34:11 +00:00
|
|
|
/// ensure that we know a router, looks up if it doesn't
|
|
|
|
void
|
|
|
|
EnsureRouterIsKnown(const RouterID& router);
|
|
|
|
|
2018-08-13 23:22:31 +00:00
|
|
|
const Identity&
|
2018-07-22 23:14:29 +00:00
|
|
|
GetIdentity()
|
|
|
|
{
|
2018-08-13 23:22:31 +00:00
|
|
|
return m_Identity;
|
2018-07-22 23:14:29 +00:00
|
|
|
}
|
2018-07-19 04:58:39 +00:00
|
|
|
|
2018-08-04 02:59:32 +00:00
|
|
|
void
|
|
|
|
PutLookup(IServiceLookup* lookup, uint64_t txid);
|
|
|
|
|
2018-08-02 00:48:43 +00:00
|
|
|
void
|
|
|
|
HandlePathBuilt(path::Path* path);
|
|
|
|
|
2018-07-12 18:21:44 +00:00
|
|
|
/// context needed to initiate an outbound hidden service session
|
|
|
|
struct OutboundContext : public llarp_pathbuilder_context
|
|
|
|
{
|
2018-07-19 21:08:11 +00:00
|
|
|
OutboundContext(const IntroSet& introSet, Endpoint* parent);
|
2018-07-12 18:21:44 +00:00
|
|
|
~OutboundContext();
|
|
|
|
|
|
|
|
/// the remote hidden service's curren intro set
|
|
|
|
IntroSet currentIntroSet;
|
2018-07-22 23:14:29 +00:00
|
|
|
/// the current selected intro
|
|
|
|
Introduction selectedIntro;
|
|
|
|
|
|
|
|
/// update the current selected intro to be a new best introduction
|
|
|
|
void
|
|
|
|
ShiftIntroduction();
|
2018-07-12 18:21:44 +00:00
|
|
|
|
2018-07-23 07:38:29 +00:00
|
|
|
/// tick internal state
|
|
|
|
/// return true to remove otherwise don't remove
|
|
|
|
bool
|
|
|
|
Tick(llarp_time_t now);
|
|
|
|
|
2018-07-12 18:21:44 +00:00
|
|
|
/// encrypt asynchronously and send to remote endpoint from us
|
2018-07-19 04:58:39 +00:00
|
|
|
void
|
|
|
|
AsyncEncryptAndSendTo(llarp_buffer_t D, ProtocolType protocol);
|
2018-07-12 18:21:44 +00:00
|
|
|
|
|
|
|
/// issues a lookup to find the current intro set of the remote service
|
|
|
|
void
|
|
|
|
UpdateIntroSet();
|
|
|
|
|
2018-08-02 00:48:43 +00:00
|
|
|
void
|
|
|
|
HandlePathBuilt(path::Path* path);
|
|
|
|
|
2018-07-19 21:08:11 +00:00
|
|
|
bool
|
|
|
|
SelectHop(llarp_nodedb* db, llarp_rc* prev, llarp_rc* cur, size_t hop);
|
|
|
|
|
2018-08-02 00:48:43 +00:00
|
|
|
bool
|
|
|
|
HandleHiddenServiceFrame(const ProtocolFrame* frame);
|
|
|
|
|
2018-08-04 02:59:32 +00:00
|
|
|
std::string
|
|
|
|
Name() const;
|
|
|
|
|
2018-07-12 18:21:44 +00:00
|
|
|
private:
|
2018-08-10 21:34:11 +00:00
|
|
|
bool
|
|
|
|
OnIntroSetUpdate(const IntroSet* i);
|
|
|
|
|
2018-07-19 04:58:39 +00:00
|
|
|
void
|
2018-08-14 21:17:18 +00:00
|
|
|
EncryptAndSendTo(path::Path* p, llarp_buffer_t payload, ProtocolType t);
|
2018-07-19 04:58:39 +00:00
|
|
|
|
|
|
|
void
|
2018-08-14 21:17:18 +00:00
|
|
|
AsyncGenIntro(path::Path* p, llarp_buffer_t payload, ProtocolType t);
|
2018-07-22 23:14:29 +00:00
|
|
|
|
|
|
|
/// send a fully encrypted hidden service frame
|
2018-07-19 04:58:39 +00:00
|
|
|
void
|
2018-07-22 23:14:29 +00:00
|
|
|
Send(ProtocolFrame& f);
|
2018-07-19 04:58:39 +00:00
|
|
|
|
|
|
|
uint64_t sequenceNo = 0;
|
2018-07-12 18:21:44 +00:00
|
|
|
llarp::SharedSecret sharedKey;
|
|
|
|
Endpoint* m_Parent;
|
2018-08-04 02:59:32 +00:00
|
|
|
uint64_t m_UpdateIntrosetTX = 0;
|
2018-07-12 18:21:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// passed a sendto context when we have a path established otherwise
|
|
|
|
// nullptr if the path was not made before the timeout
|
|
|
|
typedef std::function< void(OutboundContext*) > PathEnsureHook;
|
|
|
|
|
|
|
|
/// return false if we have already called this function before for this
|
|
|
|
/// address
|
|
|
|
bool
|
|
|
|
EnsurePathToService(const Address& remote, PathEnsureHook h,
|
|
|
|
uint64_t timeoutMS);
|
|
|
|
|
|
|
|
virtual bool
|
|
|
|
HandleAuthenticatedDataFrom(const Address& remote, llarp_buffer_t data)
|
|
|
|
{
|
|
|
|
/// TODO: imlement me
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-08-09 19:02:17 +00:00
|
|
|
void
|
|
|
|
PutSenderFor(const ConvoTag& tag, const ServiceInfo& info);
|
|
|
|
|
|
|
|
bool
|
|
|
|
GetCachedSessionKeyFor(const ConvoTag& remote,
|
2018-08-13 23:22:31 +00:00
|
|
|
const byte_t*& secret) const;
|
2018-08-09 19:02:17 +00:00
|
|
|
void
|
|
|
|
PutCachedSessionKeyFor(const ConvoTag& remote,
|
|
|
|
const SharedSecret& secret);
|
|
|
|
|
|
|
|
bool
|
|
|
|
GetSenderFor(const ConvoTag& remote, ServiceInfo& si) const;
|
|
|
|
|
|
|
|
void
|
|
|
|
PutIntroFor(const ConvoTag& remote, const Introduction& intro);
|
|
|
|
|
|
|
|
bool
|
|
|
|
GetIntroFor(const ConvoTag& remote, Introduction& intro) const;
|
|
|
|
|
|
|
|
bool
|
|
|
|
GetConvoTagsForService(const ServiceInfo& si,
|
|
|
|
std::set< ConvoTag >& tag) const;
|
|
|
|
|
2018-07-19 21:08:11 +00:00
|
|
|
void
|
|
|
|
PutNewOutboundContext(const IntroSet& introset);
|
|
|
|
|
2018-07-18 03:10:21 +00:00
|
|
|
protected:
|
|
|
|
virtual void
|
|
|
|
IntroSetPublishFail();
|
|
|
|
virtual void
|
|
|
|
IntroSetPublished();
|
|
|
|
|
|
|
|
IServiceLookup*
|
|
|
|
GenerateLookupByTag(const Tag& tag);
|
|
|
|
|
|
|
|
void
|
|
|
|
PrefetchServicesByTag(const Tag& tag);
|
|
|
|
|
2018-08-09 19:02:17 +00:00
|
|
|
uint64_t
|
|
|
|
GetSeqNoForConvo(const ConvoTag& tag);
|
|
|
|
|
|
|
|
bool
|
|
|
|
IsolateNetwork();
|
|
|
|
|
2018-08-16 14:34:15 +00:00
|
|
|
bool
|
|
|
|
NetworkIsIsolated() const;
|
|
|
|
|
2018-08-17 19:49:58 +00:00
|
|
|
static void
|
|
|
|
RunIsolatedMainLoop(void*);
|
|
|
|
|
2018-07-18 03:10:21 +00:00
|
|
|
private:
|
2018-08-10 21:34:11 +00:00
|
|
|
bool
|
|
|
|
OnOutboundLookup(const IntroSet* i); /* */
|
|
|
|
|
2018-08-09 19:02:17 +00:00
|
|
|
static bool
|
2018-08-20 19:12:12 +00:00
|
|
|
SetupIsolatedNetwork(void* user, bool success);
|
2018-08-09 19:02:17 +00:00
|
|
|
|
|
|
|
bool
|
2018-08-18 14:01:21 +00:00
|
|
|
DoNetworkIsolation(bool failed);
|
2018-08-09 19:02:17 +00:00
|
|
|
|
2018-08-16 14:34:15 +00:00
|
|
|
virtual bool
|
|
|
|
SetupNetworking()
|
|
|
|
{
|
|
|
|
// XXX: override me
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-08-18 14:01:21 +00:00
|
|
|
virtual bool
|
|
|
|
IsolationFailed()
|
|
|
|
{
|
|
|
|
// XXX: override me
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-07-18 03:10:21 +00:00
|
|
|
uint64_t
|
|
|
|
GenTXID();
|
|
|
|
|
2018-08-08 19:37:33 +00:00
|
|
|
protected:
|
|
|
|
IDataHandler* m_DataHandler = nullptr;
|
2018-08-09 19:02:17 +00:00
|
|
|
Identity m_Identity;
|
2018-08-08 19:37:33 +00:00
|
|
|
|
2018-07-09 17:32:11 +00:00
|
|
|
private:
|
|
|
|
llarp_router* m_Router;
|
2018-08-09 19:02:17 +00:00
|
|
|
llarp_threadpool* m_IsolatedWorker = nullptr;
|
|
|
|
llarp_logic* m_IsolatedLogic = nullptr;
|
2018-08-17 19:49:58 +00:00
|
|
|
llarp_ev_loop* m_IsolatedNetLoop = nullptr;
|
2018-07-09 17:32:11 +00:00
|
|
|
std::string m_Keyfile;
|
2018-07-11 16:11:19 +00:00
|
|
|
std::string m_Name;
|
2018-08-09 19:02:17 +00:00
|
|
|
std::string m_NetNS;
|
|
|
|
|
2018-07-12 18:21:44 +00:00
|
|
|
std::unordered_map< Address, OutboundContext*, Address::Hash >
|
|
|
|
m_RemoteSessions;
|
2018-07-22 23:14:29 +00:00
|
|
|
std::unordered_map< Address, PathEnsureHook, Address::Hash >
|
|
|
|
m_PendingServiceLookups;
|
2018-08-10 21:34:11 +00:00
|
|
|
|
2018-08-14 21:17:18 +00:00
|
|
|
struct RouterLookupJob
|
|
|
|
{
|
|
|
|
RouterLookupJob(Endpoint* p)
|
|
|
|
{
|
|
|
|
started = llarp_time_now_ms();
|
|
|
|
txid = p->GenTXID();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t txid;
|
|
|
|
llarp_time_t started;
|
|
|
|
|
|
|
|
bool
|
|
|
|
IsExpired(llarp_time_t now) const
|
|
|
|
{
|
|
|
|
if(now < started)
|
|
|
|
return false;
|
|
|
|
return now - started > 5000;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
std::unordered_map< RouterID, RouterLookupJob, RouterID::Hash >
|
|
|
|
m_PendingRouters;
|
2018-08-10 21:34:11 +00:00
|
|
|
|
2018-07-18 03:10:21 +00:00
|
|
|
uint64_t m_CurrentPublishTX = 0;
|
|
|
|
llarp_time_t m_LastPublish = 0;
|
|
|
|
llarp_time_t m_LastPublishAttempt = 0;
|
|
|
|
/// our introset
|
|
|
|
service::IntroSet m_IntroSet;
|
2018-07-19 21:08:11 +00:00
|
|
|
/// pending remote service lookups by id
|
2018-08-14 21:17:18 +00:00
|
|
|
std::unordered_map< uint64_t, std::unique_ptr< service::IServiceLookup > >
|
|
|
|
m_PendingLookups;
|
2018-08-02 00:48:43 +00:00
|
|
|
/// prefetch remote address list
|
|
|
|
std::set< Address > m_PrefetchAddrs;
|
2018-07-18 03:10:21 +00:00
|
|
|
/// hidden service tag
|
|
|
|
Tag m_Tag;
|
|
|
|
/// prefetch descriptors for these hidden service tags
|
|
|
|
std::set< Tag > m_PrefetchTags;
|
2018-08-09 19:02:17 +00:00
|
|
|
/// on initialize functions
|
|
|
|
std::list< std::function< bool(void) > > m_OnInit;
|
|
|
|
|
|
|
|
struct Session
|
|
|
|
{
|
|
|
|
SharedSecret sharedKey;
|
|
|
|
ServiceInfo remote;
|
|
|
|
Introduction intro;
|
|
|
|
llarp_time_t lastUsed = 0;
|
|
|
|
uint64_t seqno = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// sessions
|
|
|
|
std::unordered_map< ConvoTag, Session, ConvoTag::Hash > m_Sessions;
|
2018-07-18 03:10:21 +00:00
|
|
|
|
2018-08-14 21:17:18 +00:00
|
|
|
struct CachedTagResult
|
2018-07-18 03:10:21 +00:00
|
|
|
{
|
2018-07-19 04:58:39 +00:00
|
|
|
const static llarp_time_t TTL = 10000;
|
|
|
|
llarp_time_t lastRequest = 0;
|
2018-08-04 02:59:32 +00:00
|
|
|
llarp_time_t lastModified = 0;
|
2018-07-18 03:10:21 +00:00
|
|
|
std::set< IntroSet > result;
|
|
|
|
Tag tag;
|
|
|
|
|
2018-08-14 21:17:18 +00:00
|
|
|
CachedTagResult(const Tag& t) : tag(t)
|
2018-07-18 03:10:21 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-08-14 21:17:18 +00:00
|
|
|
~CachedTagResult()
|
|
|
|
{
|
|
|
|
}
|
2018-07-18 03:10:21 +00:00
|
|
|
|
2018-07-18 22:50:05 +00:00
|
|
|
void
|
|
|
|
Expire(llarp_time_t now);
|
|
|
|
|
2018-07-18 03:10:21 +00:00
|
|
|
bool
|
|
|
|
ShouldRefresh(llarp_time_t now) const
|
|
|
|
{
|
2018-07-19 04:58:39 +00:00
|
|
|
if(now <= lastRequest)
|
|
|
|
return false;
|
2018-08-04 02:59:32 +00:00
|
|
|
return (now - lastRequest) > TTL;
|
2018-07-18 03:10:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
llarp::routing::IMessage*
|
2018-08-14 21:17:18 +00:00
|
|
|
BuildRequestMessage(uint64_t txid);
|
2018-07-18 03:10:21 +00:00
|
|
|
|
|
|
|
bool
|
|
|
|
HandleResponse(const std::set< IntroSet >& results);
|
|
|
|
};
|
|
|
|
|
2018-08-14 21:17:18 +00:00
|
|
|
struct TagLookupJob : public IServiceLookup
|
|
|
|
{
|
|
|
|
TagLookupJob(Endpoint* parent, CachedTagResult* result)
|
|
|
|
: IServiceLookup(parent, parent->GenTXID(), "taglookup")
|
|
|
|
, m_result(result)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
~TagLookupJob()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
llarp::routing::IMessage*
|
|
|
|
BuildRequestMessage()
|
|
|
|
{
|
|
|
|
return m_result->BuildRequestMessage(txid);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
HandleResponse(const std::set< IntroSet >& results)
|
|
|
|
{
|
|
|
|
return m_result->HandleResponse(results);
|
|
|
|
}
|
|
|
|
|
|
|
|
CachedTagResult* m_result;
|
|
|
|
};
|
|
|
|
|
2018-07-18 03:10:21 +00:00
|
|
|
std::unordered_map< Tag, CachedTagResult, Tag::Hash > m_PrefetchedTags;
|
2018-07-09 17:32:11 +00:00
|
|
|
};
|
|
|
|
} // namespace service
|
|
|
|
} // namespace llarp
|
|
|
|
|
2018-08-16 14:34:15 +00:00
|
|
|
#endif
|