hidden services sorta work

pull/13/head
Jeff Becker 6 years ago
parent a9b28e5407
commit e79708c1dc
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -82,7 +82,7 @@ testnet-clean: clean
rm -rf $(TESTNET_ROOT) rm -rf $(TESTNET_ROOT)
testnet-configure: testnet-clean testnet-configure: testnet-clean
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX) -DTUNTAP=ON cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX) -DTUNTAP=ON
testnet-build: testnet-configure testnet-build: testnet-configure
ninja ninja

@ -21,12 +21,8 @@ namespace llarp
{ {
if(randomize) if(randomize)
Randomize(); Randomize();
} else
Zero();
AlignedBuffer(const AlignedBuffer& other)
{
for(size_t idx = 0; idx < (sz / 8); ++idx)
l[idx] = other.l[idx];
} }
AlignedBuffer(const byte_t* data) AlignedBuffer(const byte_t* data)
@ -68,6 +64,24 @@ namespace llarp
return memcmp(l, other.l, sz) < 0; return memcmp(l, other.l, sz) < 0;
} }
bool
operator>(const AlignedBuffer& other) const
{
return memcmp(l, other.l, sz) > 0;
}
bool
operator<=(const AlignedBuffer& other) const
{
return memcmp(l, other.l, sz) <= 0;
}
bool
operator>=(const AlignedBuffer& other) const
{
return memcmp(l, other.l, sz) >= 0;
}
AlignedBuffer AlignedBuffer
operator^(const AlignedBuffer& other) const operator^(const AlignedBuffer& other) const
{ {
@ -110,7 +124,7 @@ namespace llarp
size_t idx = sz / 8; size_t idx = sz / 8;
while(idx) while(idx)
{ {
if(l[idx--]) if(l[--idx])
return false; return false;
} }
return true; return true;

@ -14,12 +14,13 @@ namespace llarp
return bencode_write_bytestring(buf, k, 1) return bencode_write_bytestring(buf, k, 1)
&& bencode_write_bytestring(buf, t, 1); && bencode_write_bytestring(buf, t, 1);
} }
template < typename Obj_t > template < typename Obj_t >
bool bool
BEncodeWriteDictString(const char* k, const Obj_t& str, llarp_buffer_t* buf) BEncodeWriteDictString(const char* k, const Obj_t& str, llarp_buffer_t* buf)
{ {
return bencode_write_bytestring(buf, k, 1) return bencode_write_bytestring(buf, k, 1)
&& bencode_write_bytestring(buf, str.c_str(), str.size()); && bencode_write_bytestring(buf, str.data(), str.size());
} }
template < typename Obj_t > template < typename Obj_t >
@ -149,11 +150,7 @@ namespace llarp
T item; T item;
if(!item.BDecode(buf)) if(!item.BDecode(buf))
return false; return false;
result.insert(item); return result.insert(item).second;
/*
if(!result.insert(item).second)
return false;
*/
} }
if(*buf->cur != 'e') // make sure we're at a list end if(*buf->cur != 'e') // make sure we're at a list end
return false; return false;

@ -19,8 +19,7 @@ namespace llarp
Bucket(const Key_t& us) : nodes(XorMetric(us)){}; Bucket(const Key_t& us) : nodes(XorMetric(us)){};
bool bool
GetRandomNodeExcluding(Key_t& result, GetRandomNodeExcluding(Key_t& result, std::set< Key_t > exclude) const
const std::set< Key_t >& exclude) const
{ {
std::vector< Key_t > candidates; std::vector< Key_t > candidates;
for(const auto& item : nodes) for(const auto& item : nodes)
@ -53,7 +52,7 @@ namespace llarp
bool bool
FindCloseExcluding(const Key_t& target, Key_t& result, FindCloseExcluding(const Key_t& target, Key_t& result,
const std::set< Key_t >& exclude) const std::set< Key_t > exclude) const
{ {
Key_t maxdist; Key_t maxdist;
maxdist.Fill(0xff); maxdist.Fill(0xff);
@ -61,8 +60,9 @@ namespace llarp
mindist.Fill(0xff); mindist.Fill(0xff);
for(const auto& item : nodes) for(const auto& item : nodes)
{ {
if(exclude.find(item.first) != exclude.end()) if(exclude.count(item.first))
continue; continue;
auto curDist = item.first ^ target; auto curDist = item.first ^ target;
if(curDist < mindist) if(curDist < mindist)
{ {

@ -6,6 +6,7 @@
#include <llarp/dht/bucket.hpp> #include <llarp/dht/bucket.hpp>
#include <llarp/dht/key.hpp> #include <llarp/dht/key.hpp>
#include <llarp/dht/message.hpp> #include <llarp/dht/message.hpp>
#include <llarp/dht/messages/findintro.hpp>
#include <llarp/dht/node.hpp> #include <llarp/dht/node.hpp>
#include <llarp/dht/search_job.hpp> #include <llarp/dht/search_job.hpp>
#include <llarp/service/IntroSet.hpp> #include <llarp/service/IntroSet.hpp>
@ -60,7 +61,43 @@ namespace llarp
void void
LookupIntroSetForPath(const service::Address& addr, uint64_t txid, LookupIntroSetForPath(const service::Address& addr, uint64_t txid,
const llarp::PathID_t& path, const Key_t& askpeer); const llarp::PathID_t& path, Key_t askpeer);
template < typename Job, typename Result >
void
TryLookupAgain(Job* j, Result r, uint64_t R)
{
const Key_t targetKey = j->target.ToKey();
Key_t askpeer;
std::set< Key_t > exclude = j->asked;
if(!nodes->FindCloseExcluding(targetKey, askpeer, exclude))
{
j->Exausted();
delete j;
return;
}
if((OurKey() ^ targetKey) < (askpeer ^ targetKey))
{
j->Exausted();
delete j;
return;
}
auto id = ++ids;
TXOwner ownerKey;
ownerKey.node = askpeer;
ownerKey.txid = id;
SearchJob job(j->whoasked, j->txid, r, [j]() { delete j; });
pendingTX[ownerKey] = job;
auto msg = new FindIntroMessage(id, j->target);
msg->R = R;
llarp::LogInfo("asking ", askpeer, " for ", j->target.ToString(),
" with txid=", id);
DHTSendTo(askpeer, msg);
j->asked.insert(std::move(askpeer));
}
void
DHTSendTo(const Key_t& peer, IMessage* msg);
void void
LookupIntroSetRelayed(const Key_t& requester, uint64_t txid, LookupIntroSetRelayed(const Key_t& requester, uint64_t txid,

@ -21,16 +21,14 @@ namespace llarp
relayed = relay; relayed = relay;
} }
FindIntroMessage(const Key_t& from, const llarp::service::Tag& tag, FindIntroMessage(const llarp::service::Tag& tag, uint64_t txid)
uint64_t txid) : IMessage({}), N(tag), T(txid)
: IMessage(from), N(tag), T(txid)
{ {
S.Zero(); S.Zero();
} }
FindIntroMessage(const Key_t& from, const llarp::service::Address& addr, FindIntroMessage(uint64_t txid, const llarp::service::Address& addr)
uint64_t txid) : IMessage({}), S(addr), T(txid)
: IMessage(from), S(addr), T(txid)
{ {
N.Zero(); N.Zero();
} }

@ -8,11 +8,13 @@ namespace llarp
{ {
struct GotRouterMessage : public IMessage struct GotRouterMessage : public IMessage
{ {
GotRouterMessage(const Key_t& from) : IMessage(from) GotRouterMessage(const Key_t& from, bool tunneled)
: IMessage(from), relayed(tunneled)
{ {
} }
GotRouterMessage(const Key_t& from, uint64_t id, const llarp_rc* result) GotRouterMessage(const Key_t& from, uint64_t id, const llarp_rc* result,
: IMessage(from), txid(id) bool tunneled)
: IMessage(from), txid(id), relayed(tunneled)
{ {
if(result) if(result)
{ {
@ -37,6 +39,7 @@ namespace llarp
std::vector< llarp_rc > R; std::vector< llarp_rc > R;
uint64_t txid = 0; uint64_t txid = 0;
uint64_t version = 0; uint64_t version = 0;
bool relayed = false;
}; };
} // namespace dht } // namespace dht
} // namespace llarp } // namespace llarp

@ -18,9 +18,11 @@ namespace llarp
{ {
const static uint64_t JobTimeout = 30000; const static uint64_t JobTimeout = 30000;
typedef std::function< void( typedef std::function< bool(
const std::vector< llarp::service::IntroSet >&) > const std::vector< llarp::service::IntroSet >&) >
IntroSetHookFunc; IntroSetHookFunc;
typedef std::function< void(void) > DoneFunc;
SearchJob(); SearchJob();
/// for routers /// for routers
SearchJob(const Key_t& requester, uint64_t requesterTX, SearchJob(const Key_t& requester, uint64_t requesterTX,
@ -29,15 +31,15 @@ namespace llarp
/// for introsets /// for introsets
SearchJob(const Key_t& requester, uint64_t requesterTX, SearchJob(const Key_t& requester, uint64_t requesterTX,
const Key_t& target, const std::set< Key_t >& excludes, const Key_t& target, const std::set< Key_t >& excludes,
IntroSetHookFunc found); IntroSetHookFunc found, DoneFunc done);
// for introsets via tag // for introsets via tag
SearchJob(const Key_t& requester, uint64_t requseterTX, SearchJob(const Key_t& requester, uint64_t requseterTX,
IntroSetHookFunc found); IntroSetHookFunc found, DoneFunc done);
void void
FoundRouter(const llarp_rc* router) const; FoundRouter(const llarp_rc* router) const;
void bool
FoundIntros( FoundIntros(
const std::vector< llarp::service::IntroSet >& introset) const; const std::vector< llarp::service::IntroSet >& introset) const;
@ -50,6 +52,7 @@ namespace llarp
// only set if looking up router // only set if looking up router
llarp_router_lookup_job* job = nullptr; llarp_router_lookup_job* job = nullptr;
IntroSetHookFunc foundIntroHook; IntroSetHookFunc foundIntroHook;
DoneFunc onDone;
llarp_time_t started; llarp_time_t started;
Key_t requester; Key_t requester;
uint64_t requesterTX; uint64_t requesterTX;

@ -1,7 +1,7 @@
#ifndef LLARP_IWP_H_ #ifndef LLARP_IWP_HPP
#define LLARP_IWP_H_ #define LLARP_IWP_HPP
#include <llarp/crypto.h> #include <llarp/crypto.h>
#include "router.hpp" #include <string>
struct llarp_iwp_args struct llarp_iwp_args
{ {
@ -9,7 +9,7 @@ struct llarp_iwp_args
struct llarp_logic* logic; struct llarp_logic* logic;
struct llarp_threadpool* cryptoworker; struct llarp_threadpool* cryptoworker;
struct llarp_router* router; struct llarp_router* router;
const char* keyfile; std::string keyfile;
}; };
#endif #endif

@ -1,5 +1,5 @@
#pragma once #pragma once
#include <llarp/iwp.h> #include <llarp/iwp.hpp>
#include <llarp/threading.hpp> #include <llarp/threading.hpp>
#include "llarp/iwp/establish_job.hpp" #include "llarp/iwp/establish_job.hpp"
#include "router.hpp" #include "router.hpp"
@ -26,7 +26,7 @@ struct llarp_link
llarp_link *parent = nullptr; llarp_link *parent = nullptr;
llarp_udp_io udp; llarp_udp_io udp;
llarp::Addr addr; llarp::Addr addr;
char keyfile[255]; std::string keyfile;
uint32_t timeout_job_id; uint32_t timeout_job_id;
const char * const char *

@ -358,6 +358,9 @@ namespace llarp
PathSet* PathSet*
GetLocalPathSet(const PathID_t& id); GetLocalPathSet(const PathID_t& id);
routing::IMessageHandler*
GetHandler(const PathID_t& id);
bool bool
ForwardLRCM(const RouterID& nextHop, ForwardLRCM(const RouterID& nextHop,
std::deque< EncryptedFrame >& frames); std::deque< EncryptedFrame >& frames);

@ -78,6 +78,19 @@ namespace llarp
return false; return false;
} }
/// override me in subtype
virtual bool
HandleGotRouterMessage(const llarp::dht::GotRouterMessage* msg)
{
return false;
}
virtual routing::IMessageHandler*
GetDHTHandler()
{
return nullptr;
}
Path* Path*
GetEstablishedPathClosestTo(const RouterID& router) const; GetEstablishedPathClosestTo(const RouterID& router) const;
@ -87,6 +100,9 @@ namespace llarp
Path* Path*
GetPathByRouter(const RouterID& router) const; GetPathByRouter(const RouterID& router) const;
Path*
GetPathByID(const PathID_t& id) const;
bool bool
GetCurrentIntroductions( GetCurrentIntroductions(
std::set< llarp::service::Introduction >& intros) const; std::set< llarp::service::Introduction >& intros) const;

@ -19,9 +19,6 @@ namespace llarp
bool bool
IsValid(llarp_shorthash_func hashfunc) const; IsValid(llarp_shorthash_func hashfunc) const;
bool
BDecode(llarp_buffer_t* buf);
bool bool
DecodeKey(llarp_buffer_t k, llarp_buffer_t* val); DecodeKey(llarp_buffer_t k, llarp_buffer_t* val);

@ -10,14 +10,58 @@ namespace llarp
{ {
struct ServiceInfo : public llarp::IBEncodeMessage struct ServiceInfo : public llarp::IBEncodeMessage
{ {
private:
llarp::PubKey enckey; llarp::PubKey enckey;
llarp::PubKey signkey; llarp::PubKey signkey;
uint64_t version = 0;
VanityNonce vanity; VanityNonce vanity;
ServiceInfo(); public:
ServiceInfo() = default;
ServiceInfo(const ServiceInfo&& other)
{
enckey = std::move(other.enckey);
signkey = std::move(other.signkey);
version = std::move(other.version);
vanity = std::move(other.vanity);
m_CachedAddr = std::move(other.m_CachedAddr);
}
ServiceInfo(const ServiceInfo& other)
{
enckey = other.enckey;
signkey = other.signkey;
version = other.version;
vanity = other.vanity;
m_CachedAddr = other.m_CachedAddr;
}
void
RandomizeVanity()
{
vanity.Randomize();
}
bool
Verify(llarp_crypto* crypto, llarp_buffer_t payload,
const Signature& sig) const
{
return crypto->verify(signkey, payload, sig);
}
byte_t*
EncryptionPublicKey()
{
return enckey;
}
~ServiceInfo(); bool
Update(const byte_t* enc, const byte_t* sign)
{
enckey = enc;
signkey = sign;
return UpdateAddr();
}
bool bool
operator==(const ServiceInfo& other) const operator==(const ServiceInfo& other) const
@ -26,6 +70,12 @@ namespace llarp
&& version == other.version && vanity == other.vanity; && version == other.version && vanity == other.vanity;
} }
bool
operator!=(const ServiceInfo& other) const
{
return !(*this == other);
}
ServiceInfo& ServiceInfo&
operator=(const ServiceInfo& other) operator=(const ServiceInfo& other)
{ {
@ -50,7 +100,7 @@ namespace llarp
<< " v=" << i.version << " x=" << i.vanity << "]"; << " v=" << i.version << " x=" << i.vanity << "]";
} }
/// compute .loki address /// .loki address
std::string std::string
Name() const; Name() const;
@ -70,9 +120,9 @@ namespace llarp
bool bool
BDecode(llarp_buffer_t* buf) BDecode(llarp_buffer_t* buf)
{ {
if(!IBEncodeMessage::BDecode(buf)) if(IBEncodeMessage::BDecode(buf))
return false; return CalculateAddress(m_CachedAddr.data());
return CalculateAddress(m_CachedAddr); return false;
} }
bool bool

@ -25,6 +25,29 @@ namespace llarp
llarp::PoW* W = nullptr; llarp::PoW* W = nullptr;
llarp::Signature Z; llarp::Signature Z;
IntroSet() = default;
IntroSet(const IntroSet&& other)
{
A = std::move(other.A);
I = std::move(other.I);
version = std::move(other.version);
topic = std::move(other.topic);
W = std::move(other.W);
Z = std::move(other.Z);
}
IntroSet(const IntroSet& other)
{
A = other.A;
I = other.I;
version = other.version;
topic = other.topic;
if(other.W)
W = new llarp::PoW(*other.W);
Z = other.Z;
}
~IntroSet(); ~IntroSet();
IntroSet& IntroSet&
@ -73,6 +96,23 @@ namespace llarp
return out << " V=" << i.version << " Z=" << i.Z; return out << " V=" << i.version << " Z=" << i.Z;
} }
bool
IsNewerThan(const IntroSet& other) const
{
return GetNewestIntro().expiresAt > other.GetNewestIntro().expiresAt;
}
Introduction
GetNewestIntro() const
{
Introduction i;
i.expiresAt = 0;
for(const auto& intro : I)
if(intro.expiresAt > i.expiresAt)
i = intro;
return i;
}
bool bool
HasExpiredIntros(llarp_time_t now) const; HasExpiredIntros(llarp_time_t now) const;

@ -2,13 +2,14 @@
#define LLARP_SERVICE_ADDRESS_HPP #define LLARP_SERVICE_ADDRESS_HPP
#include <llarp/aligned.hpp> #include <llarp/aligned.hpp>
#include <llarp/dht/key.hpp> #include <llarp/dht/key.hpp>
#include <llarp/router_id.hpp>
#include <string> #include <string>
namespace llarp namespace llarp
{ {
namespace service namespace service
{ {
struct Address : public llarp::AlignedBuffer< 32 > struct Address
{ {
std::string std::string
ToString() const; ToString() const;
@ -16,28 +17,152 @@ namespace llarp
bool bool
FromString(const std::string& str); FromString(const std::string& str);
Address() : llarp::AlignedBuffer< 32 >() Address()
{ {
Zero();
} }
Address(const byte_t* data) : llarp::AlignedBuffer< 32 >(data) Address(const Address& other)
{ {
memcpy(b, other.b, 32);
} }
struct Hash
byte_t& operator[](size_t idx)
{ {
size_t return b[idx];
operator()(const Address& addr) const }
const byte_t& operator[](size_t idx) const
{
return b[idx];
}
bool
BEncode(llarp_buffer_t* buf) const
{
return bencode_write_bytestring(buf, b, 32);
}
bool
BDecode(llarp_buffer_t* buf)
{
llarp_buffer_t strbuf;
if(!bencode_read_string(buf, &strbuf))
return false;
if(strbuf.sz != 32)
{ {
size_t idx = 0; llarp::LogErrorTag("Address::BDecode",
memcpy(&idx, addr, sizeof(idx)); "bdecode buffer size missmatch ", strbuf.sz,
return idx; "!=32");
return false;
} }
}; memcpy(b, strbuf.base, 32);
return true;
}
operator const dht::Key_t() const size_t
size() const
{
return 32;
}
bool
IsZero() const
{
size_t sz = 4;
while(sz)
{
if(l[--sz])
return false;
}
return true;
}
void
Zero()
{
size_t sz = 4;
while(sz)
{
l[--sz] = 0;
}
}
bool
operator<(const Address& other) const
{
return memcmp(data(), other.data(), 32) < 0;
}
friend std::ostream&
operator<<(std::ostream& out, const Address& self)
{
return out << self.ToString();
}
bool
operator==(const Address& other) const
{
return memcmp(data(), other.data(), 32) == 0;
}
bool
operator!=(const Address& other) const
{
return !(*this == other);
}
Address&
operator=(const Address& other)
{
memcpy(data(), other.data(), 32);
return *this;
}
const dht::Key_t
ToKey() const
{ {
return dht::Key_t(data()); return dht::Key_t(data());
} }
const RouterID
ToRouter() const
{
return RouterID(data());
}
const byte_t*
data() const
{
return b;
}
byte_t*
data()
{
return b;
}
const uint64_t*
data_l() const
{
return l;
}
struct Hash
{
size_t
operator()(const Address& buf) const
{
return *buf.data_l();
}
};
private:
union {
byte_t b[32];
uint64_t l[4];
};
}; };
} // namespace service } // namespace service

@ -67,6 +67,9 @@ namespace llarp
bool bool
HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg); HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg);
bool
HandleGotRouterMessage(const llarp::dht::GotRouterMessage* msg);
bool bool
HandleHiddenServiceFrame(const llarp::service::ProtocolFrame* msg); HandleHiddenServiceFrame(const llarp::service::ProtocolFrame* msg);
@ -90,6 +93,10 @@ namespace llarp
// override me in subclass // override me in subclass
} }
/// ensure that we know a router, looks up if it doesn't
void
EnsureRouterIsKnown(const RouterID& router);
Identity* Identity*
GetIdentity() GetIdentity()
{ {
@ -136,9 +143,6 @@ namespace llarp
bool bool
SelectHop(llarp_nodedb* db, llarp_rc* prev, llarp_rc* cur, size_t hop); SelectHop(llarp_nodedb* db, llarp_rc* prev, llarp_rc* cur, size_t hop);
bool
HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg);
bool bool
HandleHiddenServiceFrame(const ProtocolFrame* frame); HandleHiddenServiceFrame(const ProtocolFrame* frame);
@ -149,6 +153,9 @@ namespace llarp
Name() const; Name() const;
private: private:
bool
OnIntroSetUpdate(const IntroSet* i);
void void
EncryptAndSendTo(llarp_buffer_t payload); EncryptAndSendTo(llarp_buffer_t payload);
@ -227,6 +234,9 @@ namespace llarp
IsolateNetwork(); IsolateNetwork();
private: private:
bool
OnOutboundLookup(const IntroSet* i); /* */
static bool static bool
SetupIsolatedNetwork(void* user); SetupIsolatedNetwork(void* user);
@ -252,6 +262,9 @@ namespace llarp
m_RemoteSessions; m_RemoteSessions;
std::unordered_map< Address, PathEnsureHook, Address::Hash > std::unordered_map< Address, PathEnsureHook, Address::Hash >
m_PendingServiceLookups; m_PendingServiceLookups;
std::unordered_map< RouterID, uint64_t, RouterID::Hash > m_PendingRouters;
uint64_t m_CurrentPublishTX = 0; uint64_t m_CurrentPublishTX = 0;
llarp_time_t m_LastPublish = 0; llarp_time_t m_LastPublish = 0;
llarp_time_t m_LastPublishAttempt = 0; llarp_time_t m_LastPublishAttempt = 0;

@ -82,7 +82,7 @@ namespace llarp
BEncode(llarp_buffer_t* buf) const; BEncode(llarp_buffer_t* buf) const;
bool bool
Verify(llarp_crypto* c, byte_t* signingkey) const; Verify(llarp_crypto* c, const ServiceInfo& from) const;
bool bool
HandleMessage(llarp::routing::IMessageHandler* h, llarp_router* r) const; HandleMessage(llarp::routing::IMessageHandler* h, llarp_router* r) const;

@ -13,7 +13,6 @@ namespace llarp
{ {
Tag() : llarp::AlignedBuffer< 16 >() Tag() : llarp::AlignedBuffer< 16 >()
{ {
Zero();
} }
Tag(const byte_t* d) : llarp::AlignedBuffer< 16 >(d) Tag(const byte_t* d) : llarp::AlignedBuffer< 16 >(d)
@ -36,17 +35,26 @@ namespace llarp
return *this; return *this;
} }
llarp::dht::Key_t Tag&
Key() const operator=(const std::string& str)
{ {
llarp::dht::Key_t k; #ifndef MIN
crypto_generichash(k, 32, data(), 16, nullptr, 0); #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
return k; memcpy(data(), str.data(), MIN(16UL, str.size()));
#undef MIN
#endif
return *this;
} }
std::string std::string
ToString() const; ToString() const;
bool
Empty() const
{
return ToString().empty();
}
struct Hash struct Hash
{ {
std::size_t std::size_t

@ -51,18 +51,52 @@ namespace llarp
struct PathLookupJob struct PathLookupJob
{ {
Key_t whoasked;
service::Address target;
uint64_t txid; uint64_t txid;
PathID_t pathID; PathID_t pathID;
llarp_router *m_router; llarp_router *m_router;
std::set< service::IntroSet > localIntroSets; std::set< service::IntroSet > localIntroSets;
std::set< Key_t > asked; std::set< Key_t > asked;
int m_TriesLeft = 5;
uint64_t R = 0;
PathLookupJob(llarp_router *r, const PathID_t &localpath, uint64_t tx) PathLookupJob(llarp_router *r, const PathID_t &localpath, uint64_t tx)
: txid(tx), pathID(localpath), m_router(r) : txid(tx), pathID(localpath), m_router(r)
{ {
whoasked = r->dht->impl.OurKey();
} }
void void
TryAgain()
{
--m_TriesLeft;
auto &dht = m_router->dht->impl;
llarp::LogInfo("try lookup again");
dht.TryLookupAgain(
this,
std::bind(&PathLookupJob::OnResult, this, std::placeholders::_1),
R);
}
void
Exausted()
{
llarp::LogWarn("Exausted peers for lookup");
auto path =
m_router->paths.GetByUpstream(m_router->dht->impl.OurKey(), pathID);
if(path)
{
llarp::routing::DHTMessage msg;
msg.M.push_back(new llarp::dht::GotIntroMessage(
std::vector< service::IntroSet >(), txid));
path->SendRoutingMessage(&msg, m_router);
}
else
llarp::LogError("no path for lookup pathid=", pathID);
}
bool
OnResult(const std::vector< service::IntroSet > &results) OnResult(const std::vector< service::IntroSet > &results)
{ {
auto path = auto path =
@ -73,23 +107,35 @@ namespace llarp
{ {
localIntroSets.insert(introset); localIntroSets.insert(introset);
} }
llarp::routing::DHTMessage msg;
auto sz = localIntroSets.size(); auto sz = localIntroSets.size();
std::vector< service::IntroSet > intros(sz); if(sz || target.IsZero() || m_TriesLeft == 0)
for(const auto &i : localIntroSets)
{ {
intros[--sz] = i; llarp::routing::DHTMessage msg;
std::vector< service::IntroSet > intros(sz);
for(const auto &i : localIntroSets)
{
intros[--sz] = i;
}
llarp::LogInfo("found ", sz, " introsets for txid=", txid);
msg.M.push_back(new llarp::dht::GotIntroMessage(intros, txid));
path->SendRoutingMessage(&msg, m_router);
}
else if(!target.IsZero())
{
if(m_TriesLeft)
{
TryAgain();
return false;
}
} }
llarp::LogInfo("found ", sz, " introsets for txid=", txid);
msg.M.push_back(new llarp::dht::GotIntroMessage(intros, txid));
path->SendRoutingMessage(&msg, m_router);
} }
else else
{ {
llarp::LogWarn("no local path for reply on PathTagLookupJob pathid=", llarp::LogWarn("no local path for reply on PathTagLookupJob pathid=",
pathID); pathID);
} }
delete this; return true;
} }
}; };
@ -110,8 +156,10 @@ namespace llarp
TXOwner ownerKey; TXOwner ownerKey;
ownerKey.node = peer; ownerKey.node = peer;
ownerKey.txid = id; ownerKey.txid = id;
SearchJob job(from, txid, SearchJob job(
[](const std::vector< service::IntroSet > &) {}); from, txid,
[](const std::vector< service::IntroSet > &) -> bool { return true; },
[]() {});
pendingTX[ownerKey] = job; pendingTX[ownerKey] = job;
auto msg = new llarp::DHTImmeidateMessage(peer); auto msg = new llarp::DHTImmeidateMessage(peer);
msg->msgs.push_back(new PublishIntroMessage(introset, id, S, E)); msg->msgs.push_back(new PublishIntroMessage(introset, id, S, E));
@ -130,12 +178,14 @@ namespace llarp
j->localIntroSets = FindRandomIntroSetsWithTag(tag); j->localIntroSets = FindRandomIntroSetsWithTag(tag);
SearchJob job( SearchJob job(
OurKey(), txid, OurKey(), txid,
std::bind(&PathLookupJob::OnResult, j, std::placeholders::_1)); std::bind(&PathLookupJob::OnResult, j, std::placeholders::_1),
[j]() { delete j; });
pendingTX[ownerKey] = job; pendingTX[ownerKey] = job;
auto msg = new llarp::DHTImmeidateMessage(askpeer); auto msg = new llarp::DHTImmeidateMessage(askpeer);
auto dhtmsg = new FindIntroMessage({}, tag, id); auto dhtmsg = new FindIntroMessage(tag, id);
dhtmsg->R = 5; dhtmsg->R = 5;
j->R = 5;
msg->msgs.push_back(dhtmsg); msg->msgs.push_back(dhtmsg);
llarp::LogInfo("asking ", askpeer, " for tag ", tag.ToString(), " with ", llarp::LogInfo("asking ", askpeer, " for tag ", tag.ToString(), " with ",
j->localIntroSets.size(), " local tags txid=", txid); j->localIntroSets.size(), " local tags txid=", txid);
@ -144,24 +194,29 @@ namespace llarp
void void
Context::LookupIntroSetForPath(const service::Address &addr, uint64_t txid, Context::LookupIntroSetForPath(const service::Address &addr, uint64_t txid,
const llarp::PathID_t &path, const llarp::PathID_t &path, Key_t askpeer)
const Key_t &askpeer)
{ {
auto id = ++ids; auto id = ++ids;
TXOwner ownerKey; TXOwner ownerKey;
ownerKey.node = askpeer; ownerKey.node = askpeer;
ownerKey.txid = id; ownerKey.txid = id;
PathLookupJob *j = new PathLookupJob(router, path, txid); PathLookupJob *j = new PathLookupJob(router, path, txid);
j->target = addr;
j->R = 5;
j->asked.emplace(askpeer);
Key_t us = OurKey();
j->asked.emplace(us);
SearchJob job( SearchJob job(
OurKey(), txid, OurKey(), txid,
std::bind(&PathLookupJob::OnResult, j, std::placeholders::_1)); std::bind(&PathLookupJob::OnResult, j, std::placeholders::_1),
[j]() { delete j; });
pendingTX[ownerKey] = job; pendingTX[ownerKey] = job;
auto msg = new llarp::DHTImmeidateMessage(askpeer); auto msg = new llarp::DHTImmeidateMessage(askpeer);
auto dhtmsg = new FindIntroMessage(addr, id); auto dhtmsg = new FindIntroMessage(id, addr);
dhtmsg->R = 5; dhtmsg->R = 5;
msg->msgs.push_back(dhtmsg); msg->msgs.push_back(dhtmsg);
llarp::LogInfo("askng ", askpeer, " for ", addr.ToString(), llarp::LogInfo("asking ", askpeer, " for ", addr.ToString(),
" with txid=", id); " with txid=", id);
router->SendToOrQueue(askpeer, msg); router->SendToOrQueue(askpeer, msg);
} }
@ -213,7 +268,8 @@ namespace llarp
if(target == ourKey) if(target == ourKey)
{ {
// we are the target, give them our RC // we are the target, give them our RC
replies.push_back(new GotRouterMessage(requester, txid, &router->rc)); replies.push_back(
new GotRouterMessage(requester, txid, &router->rc, false));
return; return;
} }
Key_t next; Key_t next;
@ -223,8 +279,8 @@ namespace llarp
if(next == target) if(next == target)
{ {
// we know it // we know it
replies.push_back( replies.push_back(new GotRouterMessage(
new GotRouterMessage(requester, txid, nodes->nodes[target].rc)); requester, txid, nodes->nodes[target].rc, false));
} }
else if(recursive) // are we doing a recursive lookup? else if(recursive) // are we doing a recursive lookup?
{ {
@ -234,7 +290,8 @@ namespace llarp
// so we won't ask neighboor recursively, tell them we don't have it // so we won't ask neighboor recursively, tell them we don't have it
llarp::LogInfo("we aren't closer to ", target, " than ", next, llarp::LogInfo("we aren't closer to ", target, " than ", next,
" so we end it here"); " so we end it here");
replies.push_back(new GotRouterMessage(requester, txid, nullptr)); replies.push_back(
new GotRouterMessage(requester, txid, nullptr, false));
} }
else else
{ {
@ -250,7 +307,8 @@ namespace llarp
llarp::LogInfo("we don't have ", target, llarp::LogInfo("we don't have ", target,
" and this was an iterative request so telling ", " and this was an iterative request so telling ",
requester, " that we don't have it"); requester, " that we don't have it");
replies.push_back(new GotRouterMessage(requester, txid, nullptr)); replies.push_back(
new GotRouterMessage(requester, txid, nullptr, false));
} }
} }
else else
@ -259,7 +317,8 @@ namespace llarp
llarp::LogInfo("we don't have ", target, llarp::LogInfo("we don't have ", target,
" and have no closer peers so telling ", requester, " and have no closer peers so telling ", requester,
" that we don't have it"); " that we don't have it");
replies.push_back(new GotRouterMessage(requester, txid, nullptr)); replies.push_back(
new GotRouterMessage(requester, txid, nullptr, false));
} }
} }
@ -334,6 +393,14 @@ namespace llarp
{1000, this, &handle_cleaner_timer}); {1000, this, &handle_cleaner_timer});
} }
void
Context::DHTSendTo(const Key_t &peer, IMessage *msg)
{
auto m = new llarp::DHTImmeidateMessage(peer);
m->msgs.push_back(msg);
router->SendToOrQueue(peer, m);
}
bool bool
Context::RelayRequestForPath(const llarp::PathID_t &id, const IMessage *msg) Context::RelayRequestForPath(const llarp::PathID_t &id, const IMessage *msg)
{ {
@ -351,34 +418,75 @@ namespace llarp
/// handles replying with a GIM for a lookup /// handles replying with a GIM for a lookup
struct IntroSetInformJob struct IntroSetInformJob
{ {
service::Address target;
uint64_t R = 0;
int m_TriesLeft = 5;
std::set< service::IntroSet > localIntroSets; std::set< service::IntroSet > localIntroSets;
Key_t replyNode; std::set< Key_t > asked;
Key_t whoasked;
uint64_t txid; uint64_t txid;
llarp_router *m_Router; llarp_router *m_Router;
IntroSetInformJob(llarp_router *r, const Key_t &replyTo, uint64_t id) IntroSetInformJob(llarp_router *r, const Key_t &replyTo, uint64_t id)
: replyNode(replyTo), txid(id), m_Router(r) : whoasked(replyTo), txid(id), m_Router(r)
{ {
} }
void void
Exausted()
{
auto msg = new llarp::DHTImmeidateMessage(whoasked);
msg->msgs.push_back(new GotIntroMessage({}, txid));
m_Router->SendToOrQueue(whoasked, msg);
}
void
TryAgain()
{
--m_TriesLeft;
llarp::LogInfo("try lookup again");
auto &dht = m_Router->dht->impl;
dht.TryLookupAgain(this,
std::bind(&IntroSetInformJob::OnResult, this,
std::placeholders::_1),
R);
}
bool
OnResult(const std::vector< llarp::service::IntroSet > &results) OnResult(const std::vector< llarp::service::IntroSet > &results)
{ {
for(const auto &introset : results) for(const auto &introset : results)
{ {
localIntroSets.insert(introset); localIntroSets.insert(std::move(introset));
} }
if(replyNode != m_Router->dht->impl.OurKey()) if(whoasked != m_Router->dht->impl.OurKey())
{ {
std::vector< service::IntroSet > reply; size_t sz = localIntroSets.size();
for(const auto &introset : localIntroSets) if(sz || target.IsZero() || m_TriesLeft == 0)
{ {
reply.push_back(introset); std::vector< service::IntroSet > reply;
for(const auto &introset : localIntroSets)
{
reply.push_back(std::move(introset));
}
localIntroSets.clear();
auto msg = new llarp::DHTImmeidateMessage(whoasked);
msg->msgs.push_back(new GotIntroMessage(reply, txid));
m_Router->SendToOrQueue(whoasked, msg);
} }
auto msg = new llarp::DHTImmeidateMessage(replyNode); else if(!target.IsZero())
msg->msgs.push_back(new GotIntroMessage(reply, txid)); {
m_Router->SendToOrQueue(replyNode, msg); if(m_TriesLeft)
{
TryAgain();
return false;
}
}
}
else
{
llarp::LogWarn("we asked for something without a path?");
} }
delete this; return true;
} }
}; };
@ -397,11 +505,12 @@ namespace llarp
j->localIntroSets = include; j->localIntroSets = include;
SearchJob job( SearchJob job(
whoasked, txid, whoasked, txid,
std::bind(&IntroSetInformJob::OnResult, j, std::placeholders::_1)); std::bind(&IntroSetInformJob::OnResult, j, std::placeholders::_1),
[j]() { delete j; });
pendingTX[ownerKey] = job; pendingTX[ownerKey] = job;
auto msg = new llarp::DHTImmeidateMessage(askpeer); auto msg = new llarp::DHTImmeidateMessage(askpeer);
auto dhtmsg = new FindIntroMessage({}, tag, id); auto dhtmsg = new FindIntroMessage(tag, id);
dhtmsg->R = R; dhtmsg->R = R;
msg->msgs.push_back(dhtmsg); msg->msgs.push_back(dhtmsg);
router->SendToOrQueue(askpeer, msg); router->SendToOrQueue(askpeer, msg);
@ -420,15 +529,22 @@ namespace llarp
ownerKey.node = askpeer; ownerKey.node = askpeer;
ownerKey.txid = id; ownerKey.txid = id;
IntroSetInformJob *j = new IntroSetInformJob(router, whoasked, txid); IntroSetInformJob *j = new IntroSetInformJob(router, whoasked, txid);
j->target = addr;
for(const auto &item : excludes)
j->asked.emplace(item);
j->R = R;
SearchJob job( SearchJob job(
whoasked, txid, addr, excludes, whoasked, txid, addr.ToKey(), {},
std::bind(&IntroSetInformJob::OnResult, j, std::placeholders::_1)); std::bind(&IntroSetInformJob::OnResult, j, std::placeholders::_1),
[j]() { delete j; });
pendingTX[ownerKey] = job; pendingTX[ownerKey] = job;
auto msg = new llarp::DHTImmeidateMessage(askpeer); auto msg = new llarp::DHTImmeidateMessage(askpeer);
auto dhtmsg = new FindIntroMessage({}, addr, id); auto dhtmsg = new FindIntroMessage(id, addr);
dhtmsg->R = R; dhtmsg->R = R;
msg->msgs.push_back(dhtmsg); msg->msgs.push_back(dhtmsg);
llarp::LogInfo("asking ", askpeer, " for ", addr.ToString(),
" on request of ", whoasked);
router->SendToOrQueue(askpeer, msg); router->SendToOrQueue(askpeer, msg);
} }

@ -49,15 +49,7 @@ namespace llarp
dec->msg = new FindRouterMessage(dec->From); dec->msg = new FindRouterMessage(dec->From);
break; break;
case 'S': case 'S':
if(dec->relayed) dec->msg = new GotRouterMessage(dec->From, dec->relayed);
{
llarp::LogWarn(
"GotRouterMessage found when parsing relayed DHT "
"message");
return false;
}
else
dec->msg = new GotRouterMessage(dec->From);
break; break;
case 'I': case 'I':
dec->msg = new PublishIntroMessage(); dec->msg = new PublishIntroMessage();

@ -57,9 +57,8 @@ namespace llarp
// message id // message id
if(!BEncodeWriteDictMsgType(buf, "A", "F")) if(!BEncodeWriteDictMsgType(buf, "A", "F"))
return false; return false;
if(N.IsZero()) if(N.Empty())
{ {
return false;
// r5n counter // r5n counter
if(!BEncodeWriteDictInt("R", R, buf)) if(!BEncodeWriteDictInt("R", R, buf))
return false; return false;
@ -103,8 +102,9 @@ namespace llarp
} }
Key_t peer; Key_t peer;
std::set< Key_t > exclude = {dht.OurKey(), From}; std::set< Key_t > exclude = {dht.OurKey(), From};
if(N.ToString().empty()) if(N.Empty())
{ {
llarp::LogInfo("lookup ", S.ToString());
const auto introset = dht.GetIntroSetByServiceAddress(S); const auto introset = dht.GetIntroSetByServiceAddress(S);
if(introset) if(introset)
{ {
@ -114,22 +114,34 @@ namespace llarp
} }
else else
{ {
if(R == 0 && !relayed) if(R == 0)
{ {
// we are iterative and don't have it, reply with a direct reply // we don't have it, reply with a direct reply
llarp::LogInfo("dont have intro set and no recursion");
replies.push_back(new GotIntroMessage({}, T)); replies.push_back(new GotIntroMessage({}, T));
} }
else else
{ {
const auto& us = dht.OurKey();
auto target = S.ToKey();
// we are recursive // we are recursive
if(dht.nodes->FindCloseExcluding(S, peer, exclude)) if(dht.nodes->FindCloseExcluding(target, peer, exclude))
{ {
if(relayed) if(relayed)
dht.LookupIntroSetForPath(S, T, pathID, peer); dht.LookupIntroSetForPath(S, T, pathID, peer);
else if(R >= 1)
dht.LookupIntroSet(S, From, T, peer, R - 1);
else else
dht.LookupIntroSet(S, From, T, peer, 0); {
if((us ^ target) < (peer ^ target))
{
// we are not closer than our peer to the target so don't
// revurse
replies.push_back(new GotIntroMessage({}, T));
}
else if(R >= 1)
dht.LookupIntroSet(S, From, T, peer, R - 1, exclude);
else
dht.LookupIntroSet(S, From, T, peer, 0, exclude);
}
} }
else else
{ {

@ -45,8 +45,8 @@ namespace llarp
{ {
if(llarp_rc_verify_sig(&self->router->crypto, &job->result)) if(llarp_rc_verify_sig(&self->router->crypto, &job->result))
{ {
reply.M.push_back( reply.M.push_back(new GotRouterMessage(job->target, self->txid,
new GotRouterMessage(job->target, self->txid, &job->result)); &job->result, false));
} }
llarp_rc_free(&job->result); llarp_rc_free(&job->result);
llarp_rc_clear(&job->result); llarp_rc_clear(&job->result);
@ -54,7 +54,7 @@ namespace llarp
else else
{ {
reply.M.push_back( reply.M.push_back(
new GotRouterMessage(job->target, self->txid, nullptr)); new GotRouterMessage(job->target, self->txid, nullptr, false));
} }
self->SendReply(&reply); self->SendReply(&reply);
// TODO: is this okay? // TODO: is this okay?
@ -74,7 +74,8 @@ namespace llarp
auto path = dht.router->paths.GetByUpstream(K, pathID); auto path = dht.router->paths.GetByUpstream(K, pathID);
if(path) if(path)
{ {
replies.push_back(new GotRouterMessage(K, txid, &dht.router->rc)); replies.push_back(
new GotRouterMessage(K, txid, &dht.router->rc, false));
return true; return true;
} }
return false; return false;

@ -39,8 +39,11 @@ namespace llarp
auto pending = dht.FindPendingTX(From, T); auto pending = dht.FindPendingTX(From, T);
if(pending) if(pending)
{ {
pending->FoundIntros(I); if(pending->FoundIntros(I))
dht.RemovePendingLookup(From, T); {
dht.RemovePendingLookup(From, T);
llarp::LogInfo("removed pending tx from ", From, " txid=", T);
}
return true; return true;
} }
else else

@ -61,7 +61,15 @@ namespace llarp
GotRouterMessage::HandleMessage(llarp_dht_context *ctx, GotRouterMessage::HandleMessage(llarp_dht_context *ctx,
std::vector< IMessage * > &replies) const std::vector< IMessage * > &replies) const
{ {
auto &dht = ctx->impl; auto &dht = ctx->impl;
if(relayed)
{
auto pathset = ctx->impl.router->paths.GetLocalPathSet(pathID);
if(pathset)
{
return pathset->HandleGotRouterMessage(this);
}
}
SearchJob *pending = dht.FindPendingTX(From, txid); SearchJob *pending = dht.FindPendingTX(From, txid);
if(pending) if(pending)
{ {
@ -71,7 +79,7 @@ namespace llarp
if(pending->requester != dht.OurKey()) if(pending->requester != dht.OurKey())
{ {
replies.push_back(new GotRouterMessage( replies.push_back(new GotRouterMessage(
pending->target, pending->requesterTX, &R[0])); pending->target, pending->requesterTX, &R[0], false));
} }
} }
else else
@ -101,7 +109,7 @@ namespace llarp
if(pending->requester != dht.OurKey()) if(pending->requester != dht.OurKey())
{ {
replies.push_back(new GotRouterMessage( replies.push_back(new GotRouterMessage(
pending->target, pending->requesterTX, nullptr)); pending->target, pending->requesterTX, nullptr, false));
} }
} }
} }

@ -24,8 +24,9 @@ namespace llarp
SearchJob::SearchJob(const Key_t &asker, uint64_t tx, const Key_t &key, SearchJob::SearchJob(const Key_t &asker, uint64_t tx, const Key_t &key,
const std::set< Key_t > &excludes, const std::set< Key_t > &excludes,
IntroSetHookFunc foundIntroset) IntroSetHookFunc foundIntroset, DoneFunc done)
: foundIntroHook(foundIntroset) : foundIntroHook(foundIntroset)
, onDone(done)
, started(llarp_time_now_ms()) , started(llarp_time_now_ms())
, requester(asker) , requester(asker)
, requesterTX(tx) , requesterTX(tx)
@ -35,8 +36,9 @@ namespace llarp
} }
SearchJob::SearchJob(const Key_t &asker, uint64_t tx, SearchJob::SearchJob(const Key_t &asker, uint64_t tx,
IntroSetHookFunc found) IntroSetHookFunc found, DoneFunc done)
: foundIntroHook(found) : foundIntroHook(found)
, onDone(done)
, started(llarp_time_now_ms()) , started(llarp_time_now_ms())
, requester(asker) , requester(asker)
, requesterTX(tx) , requesterTX(tx)
@ -44,12 +46,16 @@ namespace llarp
target.Zero(); target.Zero();
} }
void bool
SearchJob::FoundIntros( SearchJob::FoundIntros(
const std::vector< llarp::service::IntroSet > &introsets) const const std::vector< llarp::service::IntroSet > &introsets) const
{ {
if(foundIntroHook) if(foundIntroHook && foundIntroHook(introsets))
foundIntroHook(introsets); {
onDone();
return true;
}
return foundIntroHook == nullptr;
} }
void void

@ -6,9 +6,9 @@ llarp_link::llarp_link(const llarp_iwp_args& args)
, crypto(args.crypto) , crypto(args.crypto)
, logic(args.logic) , logic(args.logic)
, worker(args.cryptoworker) , worker(args.cryptoworker)
, keyfile(args.keyfile)
, m_name("IWP") , m_name("IWP")
{ {
strncpy(keyfile, args.keyfile, sizeof(keyfile));
iwp = llarp_async_iwp_new(crypto, logic, worker); iwp = llarp_async_iwp_new(crypto, logic, worker);
pumpingLogic.store(false); pumpingLogic.store(false);
} }
@ -206,15 +206,23 @@ llarp_link::PumpLogic()
void void
llarp_link::RemoveSession(llarp_link_session* s) llarp_link::RemoveSession(llarp_link_session* s)
{ {
lock_t lock(m_sessions_Mutex);
auto itr = m_sessions.find(s->addr);
if(itr != m_sessions.end())
{ {
UnmapAddr(s->addr); lock_t lock(m_sessions_Mutex);
s->done(); auto itr = m_sessions.find(s->addr);
m_sessions.erase(itr); if(itr != m_sessions.end())
delete s; {
UnmapAddr(s->addr);
s->done();
m_sessions.erase(itr);
}
}
{
lock_t lock(m_PendingSessions_Mutex);
auto itr = m_PendingSessions.find(s->addr);
if(itr != m_PendingSessions.end())
m_PendingSessions.erase(itr);
} }
delete s;
} }
uint8_t* uint8_t*
@ -230,7 +238,7 @@ llarp_link::ensure_privkey()
std::error_code ec; std::error_code ec;
if(!fs::exists(keyfile, ec)) if(!fs::exists(keyfile, ec))
{ {
if(!keygen(keyfile)) if(!keygen(keyfile.c_str()))
return false; return false;
} }
std::ifstream f(keyfile); std::ifstream f(keyfile);

@ -1,9 +1,9 @@
#ifdef _MSC_VER #ifdef _MSC_VER
#define NOMINMAX #define NOMINMAX
#endif #endif
#include <llarp/iwp.h>
#include <algorithm> #include <algorithm>
#include <llarp/crypto.hpp> #include <llarp/crypto.hpp>
#include <llarp/iwp.hpp>
#include <llarp/iwp/server.hpp> #include <llarp/iwp/server.hpp>
#include <llarp/iwp/session.hpp> #include <llarp/iwp/session.hpp>
#include "address_info.hpp" #include "address_info.hpp"

@ -23,7 +23,7 @@ namespace llarp
} }
} }
template < typename T, size_t align = 8 > template < typename T, size_t align = 128 >
void void
DumpBuffer(const T &buff) DumpBuffer(const T &buff)
{ {

@ -132,7 +132,7 @@ struct llarp_nodedb
llarp_rc entry; llarp_rc entry;
llarp::Zero(&entry, sizeof(entry)); llarp::Zero(&entry, sizeof(entry));
llarp_rc_copy(&entry, rc); llarp_rc_copy(&entry, rc);
entries[pk] = entry; entries.insert(std::make_pair(pk, entry));
if(llarp_rc_bencode(&entry, &buf)) if(llarp_rc_bencode(&entry, &buf))
{ {
@ -273,8 +273,9 @@ disk_threadworker_setRC(void *user)
llarp_async_verify_rc *verify_request = llarp_async_verify_rc *verify_request =
static_cast< llarp_async_verify_rc * >(user); static_cast< llarp_async_verify_rc * >(user);
verify_request->valid = verify_request->nodedb->setRC(&verify_request->rc); verify_request->valid = verify_request->nodedb->setRC(&verify_request->rc);
llarp_logic_queue_job(verify_request->logic, if(verify_request->logic)
{verify_request, &logic_threadworker_callback}); llarp_logic_queue_job(verify_request->logic,
{verify_request, &logic_threadworker_callback});
} }
// we run the crypto verify in the crypto threadpool worker // we run the crypto verify in the crypto threadpool worker

@ -263,6 +263,29 @@ namespace llarp
builder->Tick(now, m_Router); builder->Tick(now, m_Router);
} }
routing::IMessageHandler*
PathContext::GetHandler(const PathID_t& id)
{
routing::IMessageHandler* h = nullptr;
auto pathset = GetLocalPathSet(id);
if(pathset)
{
h = pathset->GetPathByID(id);
}
if(h)
return h;
RouterID us(OurRouterID());
auto& map = m_TransitPaths;
std::unique_lock< std::mutex > lock(map.first);
auto range = map.second.equal_range(id);
for(auto i = range.first; i != range.second; ++i)
{
if(i->second->info.upstream == us)
return i->second;
}
return nullptr;
}
void void
PathContext::AddPathBuilder(llarp_pathbuilder_context* ctx) PathContext::AddPathBuilder(llarp_pathbuilder_context* ctx)
{ {
@ -366,7 +389,10 @@ namespace llarp
msg->X = buf; msg->X = buf;
msg->Y = Y; msg->Y = Y;
msg->pathid = TXID(); msg->pathid = TXID();
return r->SendToOrQueue(Upstream(), msg); if(r->SendToOrQueue(Upstream(), msg))
return true;
llarp::LogError("send to ", Upstream(), " failed");
return false;
} }
bool bool
@ -411,7 +437,11 @@ namespace llarp
byte_t tmp[MAX_LINK_MSG_SIZE / 2]; byte_t tmp[MAX_LINK_MSG_SIZE / 2];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
if(!msg->BEncode(&buf)) if(!msg->BEncode(&buf))
{
llarp::LogError("Bencode failed");
llarp::DumpBuffer(buf);
return false; return false;
}
// make nonce // make nonce
TunnelNonce N; TunnelNonce N;
N.Randomize(); N.Randomize();

@ -81,6 +81,19 @@ namespace llarp
return nullptr; return nullptr;
} }
Path*
PathSet::GetPathByID(const PathID_t& id) const
{
auto itr = m_Paths.begin();
while(itr != m_Paths.end())
{
if(itr->second->RXID() == id)
return itr->second;
++itr;
}
return nullptr;
}
size_t size_t
PathSet::NumInStatus(PathStatus st) const PathSet::NumInStatus(PathStatus st) const
{ {

@ -9,13 +9,6 @@ namespace llarp
{ {
} }
bool
PoW::BDecode(llarp_buffer_t* buf)
{
// TODO: implement me
return false;
}
bool bool
PoW::DecodeKey(llarp_buffer_t k, llarp_buffer_t* val) PoW::DecodeKey(llarp_buffer_t k, llarp_buffer_t* val)
{ {
@ -27,7 +20,9 @@ namespace llarp
PoW::BEncode(llarp_buffer_t* buf) const PoW::BEncode(llarp_buffer_t* buf) const
{ {
// TODO: implement me // TODO: implement me
return false; if(!bencode_start_dict(buf))
return false;
return bencode_end(buf);
} }
bool bool

@ -1,6 +1,6 @@
#include "router.hpp" #include "router.hpp"
#include <llarp/iwp.h>
#include <llarp/proto.h> #include <llarp/proto.h>
#include <llarp/iwp.hpp>
#include <llarp/link_message.hpp> #include <llarp/link_message.hpp>
#include "llarp/iwp/establish_job.hpp" #include "llarp/iwp/establish_job.hpp"
#include "llarp/iwp/server.hpp" #include "llarp/iwp/server.hpp"
@ -745,10 +745,10 @@ llarp_router::InitOutboundLink()
return true; return true;
llarp_iwp_args args = { llarp_iwp_args args = {
&crypto, logic, tp, this, transport_keyfile.string().c_str(), &crypto, logic, tp, this, transport_keyfile.string(),
}; };
auto link = new(std::nothrow) llarp_link(args); auto link = new llarp_link(args);
auto afs = {AF_INET, AF_INET6}; auto afs = {AF_INET, AF_INET6};
@ -1093,6 +1093,7 @@ namespace llarp
const char *key, const char *val) const char *key, const char *val)
{ {
llarp_router *self = static_cast< llarp_router * >(iter->user); llarp_router *self = static_cast< llarp_router * >(iter->user);
int af; int af;
uint16_t proto; uint16_t proto;
if(StrEq(val, "eth")) if(StrEq(val, "eth"))
@ -1117,17 +1118,15 @@ namespace llarp
{ {
if(!StrEq(key, "*")) if(!StrEq(key, "*"))
{ {
llarp::LogInfo("interface specific binding activated");
llarp_iwp_args args = { llarp_iwp_args args = {
&self->crypto, &self->crypto,
self->logic, self->logic,
self->tp, self->tp,
self, self,
self->transport_keyfile.string().c_str(), self->transport_keyfile.string(),
}; };
llarp::LogInfo("interface specific binding activated");
link = new(std::nothrow) llarp_link(args); link = new llarp_link(args);
if(link) if(link)
{ {

@ -161,7 +161,6 @@ namespace llarp
bool bool
Identity::BEncode(llarp_buffer_t* buf) const Identity::BEncode(llarp_buffer_t* buf) const
{ {
/// TODO: implement me
if(!bencode_start_dict(buf)) if(!bencode_start_dict(buf))
return false; return false;
if(!BEncodeWriteDictEntry("e", enckey, buf)) if(!BEncodeWriteDictEntry("e", enckey, buf))
@ -195,10 +194,8 @@ namespace llarp
{ {
crypto->encryption_keygen(enckey); crypto->encryption_keygen(enckey);
crypto->identity_keygen(signkey); crypto->identity_keygen(signkey);
pub.enckey = llarp::seckey_topublic(enckey); pub.Update(llarp::seckey_topublic(enckey),
pub.signkey = llarp::seckey_topublic(signkey); llarp::seckey_topublic(signkey));
pub.vanity.Zero();
pub.UpdateAddr();
} }
bool bool
@ -273,7 +270,7 @@ namespace llarp
// rewind and resize buffer // rewind and resize buffer
buf.sz = buf.cur - buf.base; buf.sz = buf.cur - buf.base;
buf.cur = buf.base; buf.cur = buf.base;
return crypto->verify(A.signkey, buf, Z); return A.Verify(crypto, buf, Z);
} }
bool bool

@ -68,7 +68,6 @@ namespace llarp
{ {
if(context) if(context)
{ {
llarp::LogInfo("BEEP");
byte_t tmp[128] = {0}; byte_t tmp[128] = {0};
memcpy(tmp, "BEEP", 4); memcpy(tmp, "BEEP", 4);
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
@ -441,7 +440,7 @@ namespace llarp
Endpoint::CachedTagResult::BuildRequestMessage() Endpoint::CachedTagResult::BuildRequestMessage()
{ {
llarp::routing::DHTMessage* msg = new llarp::routing::DHTMessage(); llarp::routing::DHTMessage* msg = new llarp::routing::DHTMessage();
msg->M.push_back(new llarp::dht::FindIntroMessage({}, tag, txid)); msg->M.push_back(new llarp::dht::FindIntroMessage(tag, txid));
lastRequest = llarp_time_now_ms(); lastRequest = llarp_time_now_ms();
parent->PutLookup(this, txid); parent->PutLookup(this, txid);
return msg; return msg;
@ -450,7 +449,7 @@ namespace llarp
bool bool
Endpoint::PublishIntroSet(llarp_router* r) Endpoint::PublishIntroSet(llarp_router* r)
{ {
auto path = GetEstablishedPathClosestTo(m_Identity.pub.Addr()); auto path = GetEstablishedPathClosestTo(m_Identity.pub.Addr().ToRouter());
if(path) if(path)
{ {
m_CurrentPublishTX = llarp_randint(); m_CurrentPublishTX = llarp_randint();
@ -496,12 +495,13 @@ namespace llarp
struct HiddenServiceAddressLookup : public IServiceLookup struct HiddenServiceAddressLookup : public IServiceLookup
{ {
Address remote; Address remote;
Endpoint* endpoint; typedef std::function< bool(const IntroSet*) > HandlerFunc;
HandlerFunc handle;
HiddenServiceAddressLookup(Endpoint* p, const Address& addr, uint64_t tx) HiddenServiceAddressLookup(Endpoint* p, HandlerFunc h,
: IServiceLookup(p, tx), remote(addr), endpoint(p) const Address& addr, uint64_t tx)
: IServiceLookup(p, tx), remote(addr), handle(h)
{ {
llarp::LogInfo("New hidden service lookup for ", addr.ToString());
} }
bool bool
@ -512,12 +512,13 @@ namespace llarp
{ {
llarp::LogInfo("hidden service lookup for ", remote.ToString(), llarp::LogInfo("hidden service lookup for ", remote.ToString(),
" success"); " success");
endpoint->PutNewOutboundContext(*results.begin()); handle(&*results.begin());
} }
else else
{ {
llarp::LogInfo("no response in hidden service lookup for ", llarp::LogInfo("no response in hidden service lookup for ",
remote.ToString()); remote.ToString());
handle(nullptr);
} }
delete this; delete this;
return true; return true;
@ -527,7 +528,10 @@ namespace llarp
BuildRequestMessage() BuildRequestMessage()
{ {
llarp::routing::DHTMessage* msg = new llarp::routing::DHTMessage(); llarp::routing::DHTMessage* msg = new llarp::routing::DHTMessage();
msg->M.push_back(new llarp::dht::FindIntroMessage(remote, txid)); auto FIM = new llarp::dht::FindIntroMessage(txid, remote);
FIM->R = 5;
msg->M.push_back(FIM);
llarp::LogInfo("build request for ", remote);
return msg; return msg;
} }
}; };
@ -543,7 +547,7 @@ namespace llarp
Endpoint::PutNewOutboundContext(const llarp::service::IntroSet& introset) Endpoint::PutNewOutboundContext(const llarp::service::IntroSet& introset)
{ {
Address addr; Address addr;
introset.A.CalculateAddress(addr); introset.A.CalculateAddress(addr.data());
// only add new session if it's not there // only add new session if it's not there
if(m_RemoteSessions.find(addr) == m_RemoteSessions.end()) if(m_RemoteSessions.find(addr) == m_RemoteSessions.end())
@ -562,6 +566,55 @@ namespace llarp
} }
} }
bool
Endpoint::HandleGotRouterMessage(const llarp::dht::GotRouterMessage* msg)
{
bool success = false;
if(msg->R.size() == 1)
{
auto itr = m_PendingRouters.find(msg->R[0].pubkey);
if(itr == m_PendingRouters.end())
return false;
llarp_async_verify_rc* job = new llarp_async_verify_rc;
job->nodedb = m_Router->nodedb;
job->cryptoworker = m_Router->tp;
job->diskworker = m_Router->disk;
job->logic = nullptr;
job->hook = nullptr;
llarp_rc_clear(&job->rc);
llarp_rc_copy(&job->rc, &msg->R[0]);
llarp_nodedb_async_verify(job);
return true;
}
return success;
}
void
Endpoint::EnsureRouterIsKnown(const RouterID& router)
{
if(!llarp_nodedb_get_rc(m_Router->nodedb, router))
{
if(m_PendingRouters.find(router) == m_PendingRouters.end())
{
auto path = GetEstablishedPathClosestTo(router);
routing::DHTMessage msg;
auto txid = GenTXID();
msg.M.push_back(
new dht::FindRouterMessage({}, dht::Key_t(router), txid));
if(path->SendRoutingMessage(&msg, m_Router))
{
llarp::LogInfo(Name(), " looking up ", router);
m_PendingRouters.insert(std::make_pair(router, txid));
}
else
{
llarp::LogError("failed to send request for router lookup");
}
}
}
}
void void
Endpoint::HandlePathBuilt(path::Path* p) Endpoint::HandlePathBuilt(path::Path* p)
{ {
@ -597,11 +650,20 @@ namespace llarp
return m_Parent->HandleHiddenServiceFrame(frame); return m_Parent->HandleHiddenServiceFrame(frame);
} }
bool
Endpoint::OnOutboundLookup(const IntroSet* introset)
{
if(!introset)
return false;
PutNewOutboundContext(*introset);
return true;
}
bool bool
Endpoint::EnsurePathToService(const Address& remote, PathEnsureHook hook, Endpoint::EnsurePathToService(const Address& remote, PathEnsureHook hook,
llarp_time_t timeoutMS) llarp_time_t timeoutMS)
{ {
auto path = GetEstablishedPathClosestTo(remote); auto path = GetEstablishedPathClosestTo(remote.ToRouter());
if(!path) if(!path)
{ {
llarp::LogWarn("No outbound path for lookup yet"); llarp::LogWarn("No outbound path for lookup yet");
@ -627,10 +689,15 @@ namespace llarp
m_PendingServiceLookups.insert(std::make_pair(remote, hook)); m_PendingServiceLookups.insert(std::make_pair(remote, hook));
HiddenServiceAddressLookup* job = HiddenServiceAddressLookup* job = new HiddenServiceAddressLookup(
new HiddenServiceAddressLookup(this, remote, GenTXID()); this,
std::bind(&Endpoint::OnOutboundLookup, this, std::placeholders::_1),
remote, GenTXID());
return job->SendRequestViaPath(path, Router()); if(job->SendRequestViaPath(path, Router()))
return true;
llarp::LogError("send via path failed");
return false;
} }
Endpoint::OutboundContext::OutboundContext(const IntroSet& intro, Endpoint::OutboundContext::OutboundContext(const IntroSet& intro,
@ -649,51 +716,27 @@ namespace llarp
{ {
} }
void bool
Endpoint::OutboundContext::ShiftIntroduction() Endpoint::OutboundContext::OnIntroSetUpdate(const IntroSet* i)
{ {
for(const auto& intro : currentIntroSet.I) if(i && i->IsNewerThan(currentIntroSet))
{ {
if(intro.expiresAt > selectedIntro.expiresAt) currentIntroSet = *i;
{
selectedIntro = intro;
}
} }
return true;
} }
bool void
Endpoint::OutboundContext::HandleGotIntroMessage( Endpoint::OutboundContext::ShiftIntroduction()
const llarp::dht::GotIntroMessage* msg)
{ {
if(msg->T != m_UpdateIntrosetTX) for(const auto& intro : currentIntroSet.I)
{
llarp::LogError("unwarrented introset message txid=", msg->T);
return false;
}
auto crypto = m_Parent->Crypto();
if(msg->I.size() == 1)
{ {
// found intro set m_Parent->EnsureRouterIsKnown(selectedIntro.router);
const auto& introset = msg->I[0]; if(intro.expiresAt > selectedIntro.expiresAt)
if(introset.VerifySignature(crypto) && currentIntroSet.A == introset.A)
{
// update
currentIntroSet = introset;
// reset tx
m_UpdateIntrosetTX = 0;
// shift to newest intro
// TODO: check timestamp on introset to make sure it's new enough
ShiftIntroduction();
return true;
}
else
{ {
llarp::LogError("Signature Error for intro set ", introset); selectedIntro = intro;
return false;
} }
} }
llarp::LogError("Bad number of intro sets in response");
return false;
} }
void void
@ -761,7 +804,8 @@ namespace llarp
// set our introduction // set our introduction
self->msg.introReply = self->intro; self->msg.introReply = self->intro;
// derive session key // derive session key
self->crypto->dh_server(self->sharedKey, self->remote.enckey, self->crypto->dh_server(self->sharedKey,
self->remote.EncryptionPublicKey(),
self->m_LocalIdentity->enckey, self->frame.N); self->m_LocalIdentity->enckey, self->frame.N);
// encrypt and sign // encrypt and sign
@ -827,17 +871,18 @@ namespace llarp
void void
Endpoint::OutboundContext::UpdateIntroSet() Endpoint::OutboundContext::UpdateIntroSet()
{ {
auto path = GetEstablishedPathClosestTo(currentIntroSet.A.Addr()); auto addr = currentIntroSet.A.Addr();
auto path = m_Parent->GetEstablishedPathClosestTo(addr.ToRouter());
if(path) if(path)
{ {
if(m_UpdateIntrosetTX == 0) HiddenServiceAddressLookup* job = new HiddenServiceAddressLookup(
{ m_Parent,
m_UpdateIntrosetTX = llarp_randint(); std::bind(&Endpoint::OutboundContext::OnIntroSetUpdate, this,
routing::DHTMessage msg; std::placeholders::_1),
msg.M.push_back(new llarp::dht::FindIntroMessage( addr, m_Parent->GenTXID());
currentIntroSet.A.Addr(), m_UpdateIntrosetTX));
path->SendRoutingMessage(&msg, m_Parent->Router()); if(!job->SendRequestViaPath(path, m_Parent->Router()))
} llarp::LogError("send via path failed");
} }
else else
{ {
@ -924,7 +969,8 @@ namespace llarp
msg.sender = m_Parent->m_Identity.pub; msg.sender = m_Parent->m_Identity.pub;
msg.PutBuffer(payload); msg.PutBuffer(payload);
if(!f.EncryptAndSign(crypto, &msg, shared, currentIntroSet.A.signkey)) if(!f.EncryptAndSign(crypto, &msg, shared,
m_Parent->m_Identity.signkey))
{ {
llarp::LogError("failed to sign"); llarp::LogError("failed to sign");
return; return;

@ -6,16 +6,6 @@ namespace llarp
{ {
namespace service namespace service
{ {
ServiceInfo::ServiceInfo()
{
vanity.Zero();
m_CachedAddr.Zero();
}
ServiceInfo::~ServiceInfo()
{
}
bool bool
ServiceInfo::DecodeKey(llarp_buffer_t key, llarp_buffer_t* val) ServiceInfo::DecodeKey(llarp_buffer_t key, llarp_buffer_t* val)
{ {
@ -56,7 +46,7 @@ namespace llarp
if(m_CachedAddr.IsZero()) if(m_CachedAddr.IsZero())
{ {
Address addr; Address addr;
CalculateAddress(addr); CalculateAddress(addr.data());
return addr.ToString(); return addr.ToString();
} }
return m_CachedAddr.ToString(); return m_CachedAddr.ToString();
@ -65,9 +55,10 @@ namespace llarp
bool bool
ServiceInfo::CalculateAddress(byte_t* addr) const ServiceInfo::CalculateAddress(byte_t* addr) const
{ {
byte_t tmp[128]; byte_t tmp[256] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
assert(BEncode(&buf)); if(!BEncode(&buf))
return false;
return crypto_generichash(addr, 32, buf.base, buf.cur - buf.base, nullptr, return crypto_generichash(addr, 32, buf.base, buf.cur - buf.base, nullptr,
0) 0)
!= -1; != -1;
@ -76,7 +67,7 @@ namespace llarp
bool bool
ServiceInfo::UpdateAddr() ServiceInfo::UpdateAddr()
{ {
return CalculateAddress(m_CachedAddr); return CalculateAddress(m_CachedAddr.data());
} }
} // namespace service } // namespace service

@ -94,8 +94,6 @@ namespace llarp
{ {
if(!bencode_start_dict(buf)) if(!bencode_start_dict(buf))
return false; return false;
if(!BEncodeWriteDictMsgType(buf, "A", "H"))
return false;
if(!BEncodeWriteDictEntry("D", D, buf)) if(!BEncodeWriteDictEntry("D", D, buf))
return false; return false;
if(S == 0) if(S == 0)
@ -261,7 +259,7 @@ namespace llarp
llarp::LogError("No sender for T=", T); llarp::LogError("No sender for T=", T);
return false; return false;
} }
if(!Verify(crypto, si.signkey)) if(!Verify(crypto, si))
{ {
llarp::LogError("Signature failure"); llarp::LogError("Signature failure");
return false; return false;
@ -289,7 +287,7 @@ namespace llarp
} }
bool bool
ProtocolFrame::Verify(llarp_crypto* crypto, byte_t* signkey) const ProtocolFrame::Verify(llarp_crypto* crypto, const ServiceInfo& from) const
{ {
ProtocolFrame copy(*this); ProtocolFrame copy(*this);
// save signature // save signature
@ -305,7 +303,7 @@ namespace llarp
buf.sz = buf.cur - buf.base; buf.sz = buf.cur - buf.base;
buf.cur = buf.base; buf.cur = buf.base;
// verify // verify
result = crypto->verify(Z, buf, signkey); result = from.Verify(crypto, buf, Z);
} }
// restore signature // restore signature
return result; return result;

@ -21,7 +21,7 @@ struct HiddenServiceTest : public ::testing::Test
SetUp() SetUp()
{ {
ident.RegenerateKeys(Crypto()); ident.RegenerateKeys(Crypto());
ident.pub.vanity.Randomize(); ident.pub.RandomizeVanity();
ident.pub.UpdateAddr(); ident.pub.UpdateAddr();
} }
}; };
@ -29,7 +29,7 @@ struct HiddenServiceTest : public ::testing::Test
TEST_F(HiddenServiceTest, TestGenerateIntroSet) TEST_F(HiddenServiceTest, TestGenerateIntroSet)
{ {
llarp::service::Address addr; llarp::service::Address addr;
ASSERT_TRUE(ident.pub.CalculateAddress(addr)); ASSERT_TRUE(ident.pub.CalculateAddress(addr.data()));
llarp::service::IntroSet I; llarp::service::IntroSet I;
while(I.I.size() < 10) while(I.I.size() < 10)
{ {

Loading…
Cancel
Save