pull/3/head
Ryan Tharp 6 years ago
commit 3241655ed9

@ -54,6 +54,9 @@
"__config": "cpp", "__config": "cpp",
"__nullptr": "cpp", "__nullptr": "cpp",
"algorithm": "cpp", "algorithm": "cpp",
"io": "cpp" "io": "cpp",
"strstream": "cpp",
"numeric": "cpp",
"valarray": "cpp"
} }
} }

@ -125,6 +125,7 @@ set(LIB_SRC
llarp/nodedb.cpp llarp/nodedb.cpp
llarp/path.cpp llarp/path.cpp
llarp/pathbuilder.cpp llarp/pathbuilder.cpp
llarp/pathset.cpp
llarp/proofofwork.cpp llarp/proofofwork.cpp
llarp/relay_ack.cpp llarp/relay_ack.cpp
llarp/relay_commit.cpp llarp/relay_commit.cpp

@ -66,7 +66,7 @@ testnet-build: testnet-configure
testnet: testnet-build testnet: testnet-build
mkdir -p $(TESTNET_ROOT) mkdir -p $(TESTNET_ROOT)
python3 contrib/testnet/genconf.py --bin=$(REPO)/llarpd --svc=30 --clients=1 --dir=$(TESTNET_ROOT) --out $(TESTNET_CONF) python3 contrib/testnet/genconf.py --bin=$(REPO)/llarpd --svc=30 --clients=300 --dir=$(TESTNET_ROOT) --out $(TESTNET_CONF)
supervisord -n -d $(TESTNET_ROOT) -l $(TESTNET_LOG) -c $(TESTNET_CONF) supervisord -n -d $(TESTNET_ROOT) -l $(TESTNET_LOG) -c $(TESTNET_CONF)
test: debug-configure test: debug-configure

@ -21,12 +21,14 @@ handle_signal(int sig)
#include <llarp/router_contact.h> #include <llarp/router_contact.h>
#include <llarp/time.h> #include <llarp/time.h>
#include <fstream> #include <fstream>
#include "fs.hpp"
#include "buffer.hpp" #include "buffer.hpp"
#include "crypto.hpp" #include "crypto.hpp"
#include "fs.hpp"
#include "router.hpp" #include "router.hpp"
bool printNode(struct llarp_nodedb_iter *iter) { bool
printNode(struct llarp_nodedb_iter *iter)
{
char ftmp[68] = {0}; char ftmp[68] = {0};
const char *hexname = const char *hexname =
llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(iter->rc->pubkey, ftmp); llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(iter->rc->pubkey, ftmp);
@ -35,7 +37,6 @@ bool printNode(struct llarp_nodedb_iter *iter) {
return false; return false;
} }
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
@ -127,7 +128,8 @@ main(int argc, char *argv[])
abort(); abort();
} }
} }
if (!haveRequiredOptions) { if(!haveRequiredOptions)
{
llarp::Error("Parameters dont all have their required parameters.\n"); llarp::Error("Parameters dont all have their required parameters.\n");
return 0; return 0;
} }
@ -139,7 +141,8 @@ main(int argc, char *argv[])
} }
ctx = llarp_main_init(conffname, !TESTNET); ctx = llarp_main_init(conffname, !TESTNET);
if (!ctx) { if(!ctx)
{
llarp::Error("Cant set up context"); llarp::Error("Cant set up context");
return 0; return 0;
} }
@ -162,10 +165,12 @@ main(int argc, char *argv[])
llarp_crypto crypt; llarp_crypto crypt;
llarp_crypto_libsodium_init(&crypt); llarp_crypto_libsodium_init(&crypt);
// which is in daemon.ini config: router.encryption-privkey (defaults "encryption.key") // which is in daemon.ini config: router.encryption-privkey (defaults
// "encryption.key")
fs::path encryption_keyfile = "encryption.key"; fs::path encryption_keyfile = "encryption.key";
llarp::SecretKey encryption; llarp::SecretKey encryption;
llarp_findOrCreateEncryption(&crypt, encryption_keyfile.c_str(), &encryption); llarp_findOrCreateEncryption(&crypt, encryption_keyfile.c_str(),
&encryption);
llarp_rc_set_pubenckey(&tmp, llarp::seckey_topublic(encryption)); llarp_rc_set_pubenckey(&tmp, llarp::seckey_topublic(encryption));
// get identity public sig key // get identity public sig key
@ -206,13 +211,15 @@ main(int argc, char *argv[])
// write file // write file
llarp_rc_write(&tmp, our_rc_file_out.c_str()); llarp_rc_write(&tmp, our_rc_file_out.c_str());
} }
if (listMode) { if(listMode)
{
llarp_main_loadDatabase(ctx); llarp_main_loadDatabase(ctx);
llarp_nodedb_iter iter; llarp_nodedb_iter iter;
iter.visit = printNode; iter.visit = printNode;
llarp_main_iterateDatabase(ctx, iter); llarp_main_iterateDatabase(ctx, iter);
} }
if (importMode) { if(importMode)
{
llarp_main_loadDatabase(ctx); llarp_main_loadDatabase(ctx);
llarp::Info("Loading ", rcfname); llarp::Info("Loading ", rcfname);
llarp_rc *rc = llarp_rc_read(rcfname); llarp_rc *rc = llarp_rc_read(rcfname);
@ -223,7 +230,8 @@ main(int argc, char *argv[])
} }
llarp_main_putDatabase(ctx, rc); llarp_main_putDatabase(ctx, rc);
} }
if (exportMode) { if(exportMode)
{
llarp_main_loadDatabase(ctx); llarp_main_loadDatabase(ctx);
// llarp::Info("Looking for string: ", rcfname); // llarp::Info("Looking for string: ", rcfname);
@ -232,7 +240,8 @@ main(int argc, char *argv[])
llarp::Info("Looking for binary: ", binaryPK); llarp::Info("Looking for binary: ", binaryPK);
struct llarp_rc *rc = llarp_main_getDatabase(ctx, binaryPK.data()); struct llarp_rc *rc = llarp_main_getDatabase(ctx, binaryPK.data());
if (!rc) { if(!rc)
{
llarp::Error("Can't load RC from database"); llarp::Error("Can't load RC from database");
} }
std::string filename(rcfname); std::string filename(rcfname);

@ -39,7 +39,6 @@ llarp_main_loadDatabase(struct llarp_main *ptr);
int int
llarp_main_iterateDatabase(struct llarp_main *ptr, struct llarp_nodedb_iter i); llarp_main_iterateDatabase(struct llarp_main *ptr, struct llarp_nodedb_iter i);
/// put RC into nodeDB /// put RC into nodeDB
bool bool
llarp_main_putDatabase(struct llarp_main *ptr, struct llarp_rc *rc); llarp_main_putDatabase(struct llarp_main *ptr, struct llarp_rc *rc);
@ -47,7 +46,6 @@ llarp_main_putDatabase(struct llarp_main *ptr, struct llarp_rc *rc);
struct llarp_rc * struct llarp_rc *
llarp_main_getDatabase(struct llarp_main *ptr, byte_t *pk); llarp_main_getDatabase(struct llarp_main *ptr, byte_t *pk);
void void
llarp_main_free(struct llarp_main *ptr); llarp_main_free(struct llarp_main *ptr);

@ -83,6 +83,14 @@ namespace llarp
b[idx] = f; b[idx] = f;
} }
bool
IsZero() const
{
AlignedBuffer< sz > b;
b.Zero();
return memcmp(l, b.l, sz) == 0;
}
void void
Zero() Zero()
{ {

@ -4,6 +4,7 @@
#include <llarp/ev.h> #include <llarp/ev.h>
#include <llarp/logic.h> #include <llarp/logic.h>
#include <llarp/threadpool.h> #include <llarp/threadpool.h>
#include <llarp/time.h>
/** /**
* crypto_async.h * crypto_async.h
@ -166,6 +167,8 @@ struct iwp_async_frame
{ {
/// true if decryption succeded /// true if decryption succeded
bool success; bool success;
/// timestamp for CoDel
llarp_time_t created;
struct llarp_async_iwp *iwp; struct llarp_async_iwp *iwp;
/// a pointer to pass ourself /// a pointer to pass ourself
void *user; void *user;
@ -179,6 +182,14 @@ struct iwp_async_frame
byte_t buf[1500]; byte_t buf[1500];
}; };
/// synchronously decrypt a frame
bool
iwp_decrypt_frame(struct iwp_async_frame *frame);
/// synchronosuly encrypt a frame
bool
iwp_encrypt_frame(struct iwp_async_frame *frame);
/// decrypt iwp frame asynchronously /// decrypt iwp frame asynchronously
void void
iwp_call_async_frame_decrypt(struct llarp_async_iwp *iwp, iwp_call_async_frame_decrypt(struct llarp_async_iwp *iwp,

@ -30,9 +30,6 @@ namespace llarp
{ {
} }
bool
IsZero() const;
Key_t Key_t
operator^(const Key_t& other) const operator^(const Key_t& other) const
{ {
@ -49,8 +46,6 @@ namespace llarp
} }
}; };
extern Key_t ZeroKey;
struct Node struct Node
{ {
llarp_rc* rc; llarp_rc* rc;

@ -1,7 +1,7 @@
#ifndef LLARP_ENCODE_HPP #ifndef LLARP_ENCODE_HPP
#define LLARP_ENCODE_HPP #define LLARP_ENCODE_HPP
#include <cstdlib>
#include <stdint.h> #include <stdint.h>
#include <cstdlib>
namespace llarp namespace llarp
{ {
@ -28,8 +28,10 @@ namespace llarp
return &stack[0]; return &stack[0];
} }
int char2int(char input); int
void HexDecode(const char* src, uint8_t* target); char2int(char input);
void
HexDecode(const char* src, uint8_t* target);
} }
#endif #endif

@ -11,7 +11,10 @@
namespace llarp namespace llarp
{ {
// forward declare // forward declare
namespace path
{
struct PathContext; struct PathContext;
}
struct LR_CommitRecord struct LR_CommitRecord
{ {
@ -67,7 +70,7 @@ namespace llarp
HandleMessage(llarp_router *router) const; HandleMessage(llarp_router *router) const;
bool bool
AsyncDecrypt(PathContext *context) const; AsyncDecrypt(llarp::path::PathContext *context) const;
}; };
} // namespace llarp } // namespace llarp

@ -4,6 +4,9 @@
#include <llarp/router_contact.h> #include <llarp/router_contact.h>
#define MAXHOPS (8) #define MAXHOPS (8)
#define DEFAULT_PATH_LIFETIME (10 * 60 * 1000)
#define PATH_BUILD_TIMEOUT (30 * 1000)
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif

@ -5,10 +5,12 @@
#include <llarp/time.h> #include <llarp/time.h>
#include <llarp/aligned.hpp> #include <llarp/aligned.hpp>
#include <llarp/crypto.hpp> #include <llarp/crypto.hpp>
#include <llarp/dht.hpp>
#include <llarp/endpoint.hpp> #include <llarp/endpoint.hpp>
#include <llarp/messages/relay.hpp> #include <llarp/messages/relay.hpp>
#include <llarp/messages/relay_commit.hpp> #include <llarp/messages/relay_commit.hpp>
#include <llarp/path_types.hpp> #include <llarp/path_types.hpp>
#include <llarp/pathset.hpp>
#include <llarp/router_id.hpp> #include <llarp/router_id.hpp>
#include <llarp/routing/handler.hpp> #include <llarp/routing/handler.hpp>
#include <llarp/routing/message.hpp> #include <llarp/routing/message.hpp>
@ -19,9 +21,9 @@
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#define DEFAULT_PATH_LIFETIME (10 * 60 * 1000)
namespace llarp namespace llarp
{
namespace path
{ {
struct TransitHopInfo struct TransitHopInfo
{ {
@ -37,7 +39,8 @@ namespace llarp
operator<<(std::ostream& out, const TransitHopInfo& info) operator<<(std::ostream& out, const TransitHopInfo& info)
{ {
out << "<tx=" << info.txID << " rx=" << info.rxID; out << "<tx=" << info.txID << " rx=" << info.rxID;
out << " upstream=" << info.upstream << " downstream=" << info.downstream; out << " upstream=" << info.upstream
<< " downstream=" << info.downstream;
return out << ">"; return out << ">";
} }
@ -57,8 +60,8 @@ namespace llarp
bool bool
operator<(const TransitHopInfo& other) const operator<(const TransitHopInfo& other) const
{ {
return txID < other.txID || rxID < other.rxID || upstream < other.upstream return txID < other.txID || rxID < other.rxID
|| downstream < other.downstream; || upstream < other.upstream || downstream < other.downstream;
} }
struct Hash struct Hash
@ -100,7 +103,8 @@ namespace llarp
// handle data in upstream direction // handle data in upstream direction
virtual bool virtual bool
HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r) = 0; HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y,
llarp_router* r) = 0;
// handle data in downstream direction // handle data in downstream direction
virtual bool virtual bool
@ -165,17 +169,10 @@ namespace llarp
PathHopConfig(); PathHopConfig();
}; };
enum PathStatus
{
ePathBuilding,
ePathEstablished,
ePathTimeout,
ePathExpired
};
/// A path we made /// A path we made
struct Path : public IHopHandler, public llarp::routing::IMessageHandler struct Path : public IHopHandler, public llarp::routing::IMessageHandler
{ {
typedef std::function< void(Path*) > BuildResultHookFunc;
typedef std::vector< PathHopConfig > HopList; typedef std::vector< PathHopConfig > HopList;
HopList hops; HopList hops;
llarp_time_t buildStarted; llarp_time_t buildStarted;
@ -183,12 +180,24 @@ namespace llarp
Path(llarp_path_hops* path); Path(llarp_path_hops* path);
void
SetBuildResultHook(BuildResultHookFunc func);
bool bool
Expired(llarp_time_t now) const; Expired(llarp_time_t now) const;
bool bool
SendRoutingMessage(const llarp::routing::IMessage* msg, llarp_router* r); SendRoutingMessage(const llarp::routing::IMessage* msg, llarp_router* r);
bool
HandlePathConfirmMessage(const llarp::routing::PathConfirmMessage* msg);
bool
HandlePathLatencyMessage(const llarp::routing::PathLatencyMessage* msg);
bool
HandleDHTMessage(const llarp::dht::IMessage* msg);
bool bool
HandleRoutingMessage(llarp_buffer_t buf, llarp_router* r); HandleRoutingMessage(llarp_buffer_t buf, llarp_router* r);
@ -204,6 +213,7 @@ namespace llarp
HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r); HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r);
// Is this deprecated? // Is this deprecated?
// nope not deprecated :^DDDD
const PathID_t& const PathID_t&
TXID() const; TXID() const;
@ -215,6 +225,9 @@ namespace llarp
protected: protected:
llarp::routing::InboundMessageParser m_InboundMessageParser; llarp::routing::InboundMessageParser m_InboundMessageParser;
private:
BuildResultHookFunc m_BuiltHook;
}; };
enum PathBuildStatus enum PathBuildStatus
@ -233,6 +246,15 @@ namespace llarp
void void
ExpirePaths(); ExpirePaths();
/// called from router tick function
/// builds all paths we need to build at current tick
void
BuildPaths();
/// track a path builder with this context
void
AddPathBuilder(llarp_pathbuilder_context* set);
void void
AllowTransit(); AllowTransit();
void void
@ -257,7 +279,8 @@ namespace llarp
GetByDownstream(const RouterID& id, const PathID_t& path); GetByDownstream(const RouterID& id, const PathID_t& path);
bool bool
ForwardLRCM(const RouterID& nextHop, std::deque< EncryptedFrame >& frames); ForwardLRCM(const RouterID& nextHop,
std::deque< EncryptedFrame >& frames);
bool bool
HopIsUs(const PubKey& k) const; HopIsUs(const PubKey& k) const;
@ -269,13 +292,14 @@ namespace llarp
HandleLRDM(const RelayDownstreamMessage* msg); HandleLRDM(const RelayDownstreamMessage* msg);
void void
AddOwnPath(Path* p); AddOwnPath(PathSet* set, Path* p);
typedef std::multimap< PathID_t, TransitHop* > TransitHopsMap_t; typedef std::multimap< PathID_t, TransitHop* > TransitHopsMap_t;
typedef std::pair< std::mutex, TransitHopsMap_t > SyncTransitMap_t; typedef std::pair< std::mutex, TransitHopsMap_t > SyncTransitMap_t;
typedef std::map< PathID_t, Path* > OwnedPathsMap_t; // maps path id -> pathset owner of path
typedef std::map< PathID_t, PathSet* > OwnedPathsMap_t;
typedef std::pair< std::mutex, OwnedPathsMap_t > SyncOwnedPathsMap_t; typedef std::pair< std::mutex, OwnedPathsMap_t > SyncOwnedPathsMap_t;
@ -302,9 +326,10 @@ namespace llarp
SyncTransitMap_t m_TransitPaths; SyncTransitMap_t m_TransitPaths;
SyncTransitMap_t m_Paths; SyncTransitMap_t m_Paths;
SyncOwnedPathsMap_t m_OurPaths; SyncOwnedPathsMap_t m_OurPaths;
std::list< llarp_pathbuilder_context* > m_PathBuilders;
bool m_AllowTransit; bool m_AllowTransit;
}; };
} // namespace path
} // namespace llarp } // namespace llarp
#endif #endif

@ -0,0 +1,63 @@
#ifndef LLARP_PATHSET_HPP
#define LLARP_PATHSET_HPP
#include <llarp/path_types.hpp>
#include <map>
#include <tuple>
namespace llarp
{
namespace path
{
enum PathStatus
{
ePathBuilding,
ePathEstablished,
ePathTimeout,
ePathExpired
};
// forward declare
struct Path;
/// a set of paths owned by an entity
struct PathSet
{
/// construct
/// @params numPaths the number of paths to maintain
PathSet(size_t numPaths);
void
RemovePath(Path* path);
void
HandlePathBuilt(Path* path);
void
AddPath(Path* path);
Path*
GetByUpstream(const RouterID& remote, const PathID_t& rxid);
void
ExpirePaths(llarp_time_t now);
size_t
NumInStatus(PathStatus st) const;
/// return true if we should build another path
bool
ShouldBuildMore() const;
private:
typedef std::map< PathID_t, Path* > PathMap_t;
// (tx,rx)
typedef std::tuple< PathMap_t, PathMap_t > PathContainer_t;
size_t m_NumPaths;
PathContainer_t m_Paths;
};
} // namespace path
} // namespace llarp
#endif

@ -2,6 +2,9 @@
#define LLARP_ROUTING_HANDLER_HPP #define LLARP_ROUTING_HANDLER_HPP
#include <llarp/buffer.h> #include <llarp/buffer.h>
#include <llarp/dht.hpp>
#include <llarp/messages/path_confirm.hpp>
#include <llarp/messages/path_latency.hpp>
namespace llarp namespace llarp
{ {
@ -12,6 +15,15 @@ namespace llarp
{ {
virtual bool virtual bool
HandleHiddenServiceData(llarp_buffer_t buf) = 0; HandleHiddenServiceData(llarp_buffer_t buf) = 0;
virtual bool
HandlePathConfirmMessage(const PathConfirmMessage* msg) = 0;
virtual bool
HandlePathLatencyMessage(const PathLatencyMessage* msg) = 0;
virtual bool
HandleDHTMessage(const llarp::dht::IMessage* msg) = 0;
}; };
} // namespace routing } // namespace routing
} // namespace llarp } // namespace llarp

@ -7,7 +7,6 @@ namespace llarp
{ {
namespace api namespace api
{ {
bool bool
CreateSessionMessage::DecodeParams(llarp_buffer_t *buf) CreateSessionMessage::DecodeParams(llarp_buffer_t *buf)
{ {

@ -0,0 +1,74 @@
#ifndef LLARP_CODEL_QUEUE_HPP
#define LLARP_CODEL_QUEUE_HPP
#include <llarp/time.h>
#include <cmath>
#include <functional>
#include <mutex>
#include <queue>
namespace llarp
{
namespace util
{
template < typename T, typename GetTime, llarp_time_t dropMs = 20,
llarp_time_t initialIntervalMs = 100 >
struct CoDelQueue
{
struct CoDelCompare
{
GetTime getTime = GetTime();
bool
operator()(const T& left, const T& right) const
{
return getTime(left) < getTime(right);
}
};
void
Put(T* item)
{
std::unique_lock< std::mutex > lock(m_QueueMutex);
m_Queue.push(*item);
}
void
Process(std::queue< T >& result)
{
llarp_time_t lowest = 0xFFFFFFFFFFFFFFFFUL;
auto start = llarp_time_now_ms();
std::unique_lock< std::mutex > lock(m_QueueMutex);
while(m_Queue.size())
{
const auto& item = m_Queue.top();
auto dlt = start - getTime(item);
lowest = std::min(dlt, lowest);
if(m_Queue.size() == 1)
{
if(lowest > dropMs)
{
// drop
nextTickInterval = initialIntervalMs / std::sqrt(++dropNum);
m_Queue.pop();
return;
}
else
{
nextTickInterval = initialIntervalMs;
dropNum = 0;
}
}
result.push(item);
m_Queue.pop();
}
}
GetTime getTime = GetTime();
size_t dropNum = 0;
llarp_time_t nextTickInterval = initialIntervalMs;
std::mutex m_QueueMutex;
std::priority_queue< T, std::vector< T >, CoDelCompare > m_Queue;
};
} // namespace util
} // namespace llarp
#endif

@ -333,6 +333,34 @@ namespace iwp
hmac_then_decrypt(void *user) hmac_then_decrypt(void *user)
{ {
iwp_async_frame *frame = static_cast< iwp_async_frame * >(user); iwp_async_frame *frame = static_cast< iwp_async_frame * >(user);
iwp_decrypt_frame(frame);
// inform result
llarp_logic_queue_job(frame->iwp->logic, {frame, &inform_frame_done});
}
void
encrypt_then_hmac(void *user)
{
iwp_async_frame *frame = static_cast< iwp_async_frame * >(user);
iwp_encrypt_frame(frame);
// call result RIGHT HERE
frame->hook(frame);
delete frame;
}
} // namespace iwp
extern "C" {
void
iwp_call_async_keygen(struct llarp_async_iwp *iwp,
struct iwp_async_keygen *keygen)
{
keygen->iwp = iwp;
llarp_threadpool_queue_job(iwp->worker, {keygen, &iwp::keygen});
}
bool
iwp_decrypt_frame(struct iwp_async_frame *frame)
{
auto crypto = frame->iwp->crypto; auto crypto = frame->iwp->crypto;
byte_t *hmac = frame->buf; byte_t *hmac = frame->buf;
byte_t *nonce = frame->buf + 32; byte_t *nonce = frame->buf + 32;
@ -354,17 +382,12 @@ namespace iwp
buf.cur = buf.base; buf.cur = buf.base;
buf.sz = frame->sz - 64; buf.sz = frame->sz - 64;
crypto->xchacha20(buf, frame->sessionkey, nonce); crypto->xchacha20(buf, frame->sessionkey, nonce);
// call result RIGHT HERE return frame->success;
// frame->hook(frame);
// delete frame;
// inform result
llarp_logic_queue_job(frame->iwp->logic, {frame, &inform_frame_done});
} }
void bool
encrypt_then_hmac(void *user) iwp_encrypt_frame(struct iwp_async_frame *frame)
{ {
iwp_async_frame *frame = static_cast< iwp_async_frame * >(user);
auto crypto = frame->iwp->crypto; auto crypto = frame->iwp->crypto;
byte_t *hmac = frame->buf; byte_t *hmac = frame->buf;
byte_t *nonce = frame->buf + 32; byte_t *nonce = frame->buf + 32;
@ -384,19 +407,7 @@ namespace iwp
buf.cur = buf.base; buf.cur = buf.base;
buf.sz = frame->sz - 32; buf.sz = frame->sz - 32;
crypto->hmac(hmac, buf, frame->sessionkey); crypto->hmac(hmac, buf, frame->sessionkey);
// call result RIGHT HERE return true;
frame->hook(frame);
delete frame;
}
} // namespace iwp
extern "C" {
void
iwp_call_async_keygen(struct llarp_async_iwp *iwp,
struct iwp_async_keygen *keygen)
{
keygen->iwp = iwp;
llarp_threadpool_queue_job(iwp->worker, {keygen, &iwp::keygen});
} }
void void

@ -81,14 +81,6 @@ namespace llarp
namespace dht namespace dht
{ {
Key_t ZeroKey;
bool
Key_t::IsZero() const
{
return memcmp(l, ZeroKey.l, 32) == 0;
}
GotRouterMessage::~GotRouterMessage() GotRouterMessage::~GotRouterMessage()
{ {
for(auto &rc : R) for(auto &rc : R)

@ -3,8 +3,8 @@
namespace llarp namespace llarp
{ {
int
int char2int(char input) char2int(char input)
{ {
if(input >= '0' && input <= '9') if(input >= '0' && input <= '9')
return input - '0'; return input - '0';
@ -15,7 +15,8 @@ namespace llarp
throw std::invalid_argument("Invalid input string"); throw std::invalid_argument("Invalid input string");
} }
void HexDecode(const char* src, uint8_t* target) void
HexDecode(const char* src, uint8_t* target)
{ {
while(*src && src[1]) while(*src && src[1])
{ {
@ -23,5 +24,4 @@ namespace llarp
src += 2; src += 2;
} }
} }
} }

@ -4,6 +4,7 @@
#include <llarp/time.h> #include <llarp/time.h>
#include <llarp/crypto.hpp> #include <llarp/crypto.hpp>
#include "address_info.hpp" #include "address_info.hpp"
#include "codel.hpp"
#include "link/encoder.hpp" #include "link/encoder.hpp"
#include <sodium/crypto_sign_ed25519.h> #include <sodium/crypto_sign_ed25519.h>
@ -657,6 +658,16 @@ namespace iwp
} }
}; };
/// get the time from a iwp_async_frame
struct FrameGetTime
{
llarp_time_t
operator()(const iwp_async_frame &frame) const
{
return frame.created;
}
};
struct session struct session
{ {
llarp_udp_io *udp; llarp_udp_io *udp;
@ -676,9 +687,22 @@ namespace iwp
llarp_link_establish_job *establish_job = nullptr; llarp_link_establish_job *establish_job = nullptr;
/// cached timestamp for frame creation
llarp_time_t now;
uint32_t establish_job_id = 0; uint32_t establish_job_id = 0;
uint32_t frames = 0; uint32_t frames = 0;
bool working = false; bool working = false;
llarp::util::CoDelQueue< iwp_async_frame, FrameGetTime > inboundFrames;
llarp::util::CoDelQueue< iwp_async_frame, FrameGetTime > outboundFrames;
std::mutex m_DecryptedFramesMutex;
std::queue< iwp_async_frame > decryptedFrames;
std::mutex m_EncryptedFramesMutex;
std::queue< iwp_async_frame > encryptedFrames;
uint32_t pump_send_timer_id = 0;
uint32_t pump_recv_timer_id = 0;
llarp::Addr addr; llarp::Addr addr;
iwp_async_intro intro; iwp_async_intro intro;
iwp_async_introack introack; iwp_async_introack introack;
@ -770,21 +794,50 @@ namespace iwp
return false; return false;
} }
static void
handle_codel_inbound_pump(void *u, uint64_t orig, uint64_t left);
static void
handle_codel_outbound_pump(void *u, uint64_t orig, uint64_t left);
void
PumpCrypto();
void
PumpCodelInbound()
{
pump_recv_timer_id = llarp_logic_call_later(
logic,
{inboundFrames.nextTickInterval, this, &handle_codel_inbound_pump});
}
void
PumpCodelOutbound()
{
pump_send_timer_id = llarp_logic_call_later(
logic,
{outboundFrames.nextTickInterval, this, &handle_codel_outbound_pump});
}
void void
pump() pump()
{ {
// TODO: in codel the timestamp may cause excssive drop when all the
// packets have a similar timestamp
now = llarp_time_now_ms();
llarp_buffer_t buf; llarp_buffer_t buf;
while(frame.next_frame(&buf)) while(frame.next_frame(&buf))
{ {
encrypt_frame_async_send(buf.base, buf.sz); encrypt_frame_async_send(buf.base, buf.sz);
frame.pop_next_frame(); frame.pop_next_frame();
} }
PumpCrypto();
} }
// this is called from net thread // this is called from net thread
void void
recv(const void *buf, size_t sz) recv(const void *buf, size_t sz)
{ {
now = llarp_time_now_ms();
switch(state) switch(state)
{ {
case eInitial: case eInitial:
@ -832,9 +885,11 @@ namespace iwp
crypto->shorthash(digest, buf); crypto->shorthash(digest, buf);
auto id = frame.txids++; auto id = frame.txids++;
auto msg = new transit_message(buf, digest, id); auto msg = new transit_message(buf, digest, id);
// enter state
EnterState(eLIMSent);
// put into outbound send queue // put into outbound send queue
add_outbound_message(id, msg); add_outbound_message(id, msg);
EnterState(eLIMSent);
} }
else else
llarp::Error("LIM Encode failed"); llarp::Error("LIM Encode failed");
@ -845,43 +900,10 @@ namespace iwp
// return true if we should be removed // return true if we should be removed
bool bool
Tick(uint64_t now) Tick(uint64_t now);
{
if(timedout(now, SESSION_TIMEOUT))
{
// we are timed out
// when we are done doing stuff with all of our frames from the crypto
// workers we are done
llarp::Debug(addr, " timed out with ", frames, " frames left");
if(working)
return false;
return frames == 0;
}
if(is_invalidated())
{
// both sides agreeed to session invalidation
// terminate our session when all of our frames from the crypto workers
// are done
llarp::Debug(addr, " invaldiated session with ", frames,
" frames left");
if(working)
return false;
return frames == 0;
}
// send keepalive if we are established or a session is made
if(state == eEstablished || state == eLIMSent)
send_keepalive(this);
// pump frames
if(state == eEstablished)
{
frame.retransmit();
pump();
}
// TODO: determine if we are too idle static void
return false; codel_timer_handler(void *user, uint64_t orig, uint64_t left);
}
bool bool
IsEstablished() IsEstablished()
@ -1001,13 +1023,11 @@ namespace iwp
{ {
session *self = static_cast< session * >(frame->user); session *self = static_cast< session * >(frame->user);
llarp::Debug("rx ", frame->sz, " frames=", self->frames); llarp::Debug("rx ", frame->sz, " frames=", self->frames);
self->frames--;
if(frame->success) if(frame->success)
{ {
if(self->frame.process(frame->buf + 64, frame->sz - 64)) if(self->frame.process(frame->buf + 64, frame->sz - 64))
{ {
self->frame.alive(); self->frame.alive();
self->pump();
} }
else else
llarp::Error("invalid frame from ", self->addr); llarp::Error("invalid frame from ", self->addr);
@ -1021,14 +1041,38 @@ namespace iwp
{ {
if(sz > 64) if(sz > 64)
{ {
iwp_async_frame *frame = alloc_frame(buf, sz); alloc_frame(inboundFrames, buf, sz);
frame->hook = &handle_frame_decrypt;
iwp_call_async_frame_decrypt(iwp, frame);
} }
else else
llarp::Warn("short packet of ", sz, " bytes"); llarp::Warn("short packet of ", sz, " bytes");
} }
static void
handle_crypto_pump(void *u);
void
DecryptInboundFrames()
{
std::queue< iwp_async_frame > outq;
std::queue< iwp_async_frame > inq;
inboundFrames.Process(inq);
while(inq.size())
{
auto &front = inq.front();
if(iwp_decrypt_frame(&front))
outq.push(front);
inq.pop();
}
{
std::unique_lock< std::mutex > lock(m_DecryptedFramesMutex);
while(outq.size())
{
decryptedFrames.push(outq.front());
outq.pop();
}
}
}
static void static void
handle_frame_encrypt(iwp_async_frame *frame) handle_frame_encrypt(iwp_async_frame *frame)
{ {
@ -1037,23 +1081,26 @@ namespace iwp
if(llarp_ev_udp_sendto(self->udp, self->addr, frame->buf, frame->sz) if(llarp_ev_udp_sendto(self->udp, self->addr, frame->buf, frame->sz)
== -1) == -1)
llarp::Warn("sendto failed"); llarp::Warn("sendto failed");
self->frames--;
} }
template < typename Queue >
iwp_async_frame * iwp_async_frame *
alloc_frame(const void *buf, size_t sz) alloc_frame(Queue &q, const void *buf, size_t sz)
{ {
// TODO don't hard code 1500 // TODO don't hard code 1500
if(sz > 1500) if(sz > 1500)
return nullptr; return nullptr;
iwp_async_frame *frame = new iwp_async_frame(); iwp_async_frame *frame = new iwp_async_frame;
if(buf) if(buf)
memcpy(frame->buf, buf, sz); memcpy(frame->buf, buf, sz);
frame->iwp = iwp;
frame->sz = sz; frame->sz = sz;
frame->user = this; frame->user = this;
frame->sessionkey = sessionkey; frame->sessionkey = sessionkey;
frames++; /// TODO: this could be rather slow
frame->created = now;
q.Put(frame);
return frame; return frame;
} }
@ -1061,14 +1108,35 @@ namespace iwp
encrypt_frame_async_send(const void *buf, size_t sz) encrypt_frame_async_send(const void *buf, size_t sz)
{ {
// 64 bytes frame overhead for nonce and hmac // 64 bytes frame overhead for nonce and hmac
iwp_async_frame *frame = alloc_frame(nullptr, sz + 64); iwp_async_frame *frame = alloc_frame(outboundFrames, nullptr, sz + 64);
memcpy(frame->buf + 64, buf, sz); memcpy(frame->buf + 64, buf, sz);
auto padding = rand() % MAX_PAD; auto padding = rand() % MAX_PAD;
if(padding) if(padding)
crypto->randbytes(frame->buf + 64 + sz, padding); crypto->randbytes(frame->buf + 64 + sz, padding);
frame->sz += padding; frame->sz += padding;
frame->hook = &handle_frame_encrypt; }
iwp_call_async_frame_encrypt(iwp, frame);
void
EncryptOutboundFrames()
{
std::queue< iwp_async_frame > q;
std::queue< iwp_async_frame > outq;
outboundFrames.Process(outq);
while(outq.size())
{
auto &front = outq.front();
if(iwp_encrypt_frame(&front))
q.push(front);
outq.pop();
}
{
std::unique_lock< std::mutex > lock(m_EncryptedFramesMutex);
while(q.size())
{
encryptedFrames.push(q.front());
q.pop();
}
}
} }
static void static void
@ -1203,6 +1271,11 @@ namespace iwp
{ {
frame.alive(); frame.alive();
state = st; state = st;
if(state == eLIMSent || state == eSessionStartSent)
{
PumpCodelInbound();
PumpCodelOutbound();
}
} }
}; };
@ -1216,13 +1289,14 @@ namespace iwp
llarp_crypto *crypto; llarp_crypto *crypto;
llarp_ev_loop *netloop; llarp_ev_loop *netloop;
llarp_async_iwp *iwp; llarp_async_iwp *iwp;
llarp_threadpool *worker;
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]; char keyfile[255];
uint32_t timeout_job_id; uint32_t timeout_job_id;
typedef std::unordered_map< llarp::Addr, llarp_link_session, typedef std::unordered_map< llarp::Addr, llarp_link_session *,
llarp::addrhash > llarp::addrhash >
LinkMap_t; LinkMap_t;
@ -1243,6 +1317,7 @@ namespace iwp
router = r; router = r;
crypto = c; crypto = c;
logic = l; logic = l;
worker = w;
iwp = llarp_async_iwp_new(crypto, logic, w); iwp = llarp_async_iwp_new(crypto, logic, w);
} }
@ -1277,7 +1352,7 @@ namespace iwp
std::set< llarp::Addr > remove; std::set< llarp::Addr > remove;
for(auto &itr : m_sessions) for(auto &itr : m_sessions)
{ {
session *s = static_cast< session * >(itr.second.impl); session *s = static_cast< session * >(itr.second->impl);
if(s && s->Tick(now)) if(s && s->Tick(now))
remove.insert(itr.first); remove.insert(itr.first);
} }
@ -1300,7 +1375,7 @@ namespace iwp
auto inner_itr = serv->m_sessions.find(itr->second); auto inner_itr = serv->m_sessions.find(itr->second);
if(inner_itr != serv->m_sessions.end()) if(inner_itr != serv->m_sessions.end())
{ {
llarp_link_session *link = &inner_itr->second; llarp_link_session *link = inner_itr->second;
return link->sendto(link, buf); return link->sendto(link, buf);
} }
} }
@ -1350,29 +1425,29 @@ namespace iwp
if(itr == m_sessions.end()) if(itr == m_sessions.end())
return nullptr; return nullptr;
else else
return static_cast< session * >(itr->second.impl); return static_cast< session * >(itr->second->impl);
} }
void void
put_session(const llarp::Addr &src, session *impl) put_session(const llarp::Addr &src, session *impl)
{ {
llarp_link_session s = {}; llarp_link_session *s = new llarp_link_session;
s.impl = impl; s->impl = impl;
s.sendto = &session::sendto; s->sendto = &session::sendto;
s.timeout = &session::is_timedout; s->timeout = &session::is_timedout;
s.close = &session::close; s->close = &session::close;
s.get_remote_router = &session::get_remote_router; s->get_remote_router = &session::get_remote_router;
s.established = &session::set_established; s->established = &session::set_established;
s.get_parent = &session::get_parent; s->get_parent = &session::get_parent;
{ {
lock_t lock(m_sessions_Mutex); lock_t lock(m_sessions_Mutex);
m_sessions[src] = s; m_sessions.emplace(src, s);
impl->parent = &m_sessions[src]; impl->parent = m_sessions[src];
}
impl->frame.router = router; impl->frame.router = router;
impl->frame.parent = impl->parent; impl->frame.parent = impl->parent;
impl->our_router = &router->rc; impl->our_router = &router->rc;
} }
}
void void
clear_sessions() clear_sessions()
@ -1381,8 +1456,9 @@ namespace iwp
auto itr = m_sessions.begin(); auto itr = m_sessions.begin();
while(itr != m_sessions.end()) while(itr != m_sessions.end())
{ {
session *s = static_cast< session * >(itr->second.impl); session *s = static_cast< session * >(itr->second->impl);
delete s; delete s;
delete itr->second;
itr = m_sessions.erase(itr); itr = m_sessions.erase(itr);
} }
} }
@ -1395,16 +1471,10 @@ namespace iwp
{ {
llarp::Debug("removing session ", addr); llarp::Debug("removing session ", addr);
UnmapAddr(addr); UnmapAddr(addr);
session *s = static_cast< session * >(itr->second.impl); session *s = static_cast< session * >(itr->second->impl);
s->done(); s->done();
m_sessions.erase(addr); delete itr->second;
if(s->frames) m_sessions.erase(itr);
{
llarp::Warn("session has ", s->frames,
" left but is idle, not deallocating session so we "
"leak but don't die");
}
else
delete s; delete s;
} }
} }
@ -1556,7 +1626,6 @@ namespace iwp
{ {
llarp::Error("intro verify failed from ", self->addr, " via ", llarp::Error("intro verify failed from ", self->addr, " via ",
self->serv->addr); self->serv->addr);
delete self;
return; return;
} }
self->intro_ack(); self->intro_ack();
@ -1575,11 +1644,20 @@ namespace iwp
void void
session::done() session::done()
{ {
auto logic = serv->logic;
if(establish_job_id) if(establish_job_id)
{ {
llarp_logic_remove_call(logic, establish_job_id); llarp_logic_remove_call(logic, establish_job_id);
handle_establish_timeout(this, 0, 0); handle_establish_timeout(this, 0, 0);
} }
if(pump_recv_timer_id)
{
llarp_logic_remove_call(logic, pump_recv_timer_id);
}
if(pump_send_timer_id)
{
llarp_logic_remove_call(logic, pump_send_timer_id);
}
} }
void void
@ -1625,6 +1703,7 @@ namespace iwp
hdr.flags() = self->frame.txflags; hdr.flags() = self->frame.txflags;
// send frame after encrypting // send frame after encrypting
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
self->now = llarp_time_now_ms();
self->encrypt_frame_async_send(buf.base, buf.sz); self->encrypt_frame_async_send(buf.base, buf.sz);
} }
@ -1663,7 +1742,6 @@ namespace iwp
if(msg->completed()) if(msg->completed())
{ {
llarp::Debug("message transmitted msgid=", msgid); llarp::Debug("message transmitted msgid=", msgid);
session *impl = static_cast< session * >(parent->impl);
tx.erase(msgid); tx.erase(msgid);
delete msg; delete msg;
} }
@ -1699,6 +1777,97 @@ namespace iwp
link->session_start(); link->session_start();
} }
bool
session::Tick(llarp_time_t now)
{
if(timedout(now, SESSION_TIMEOUT))
{
// we are timed out
// when we are done doing stuff with all of our frames from the crypto
// workers we are done
llarp::Debug(addr, " timed out with ", frames, " frames left");
return !working;
}
if(is_invalidated())
{
// both sides agreeed to session invalidation
// terminate our session when all of our frames from the crypto workers
// are done
llarp::Debug(addr, " invaldiated session with ", frames, " frames left");
return !working;
}
// send keepalive if we are established or a session is made
if(state == eEstablished || state == eLIMSent)
send_keepalive(this);
// pump frame state
if(state == eEstablished)
{
frame.retransmit();
pump();
}
// TODO: determine if we are too idle
return false;
}
void
session::handle_codel_outbound_pump(void *u, uint64_t orig, uint64_t left)
{
if(left)
return;
session *self = static_cast< session * >(u);
self->pump_send_timer_id = 0;
if(self->timedout(llarp_time_now_ms()))
return;
{
std::unique_lock< std::mutex > lock(self->m_EncryptedFramesMutex);
while(self->encryptedFrames.size())
{
auto &front = self->encryptedFrames.front();
handle_frame_encrypt(&front);
self->encryptedFrames.pop();
}
}
self->PumpCodelOutbound();
self->PumpCrypto();
}
void
session::handle_codel_inbound_pump(void *u, uint64_t orig, uint64_t left)
{
if(left)
return;
session *self = static_cast< session * >(u);
self->pump_recv_timer_id = 0;
if(self->timedout(llarp_time_now_ms()))
return;
{
std::unique_lock< std::mutex > lock(self->m_DecryptedFramesMutex);
while(self->decryptedFrames.size())
{
auto &front = self->decryptedFrames.front();
handle_frame_decrypt(&front);
self->decryptedFrames.pop();
}
}
self->PumpCodelInbound();
self->PumpCrypto();
}
void
session::PumpCrypto()
{
llarp_threadpool_queue_job(serv->worker, {this, &handle_crypto_pump});
}
void
session::handle_crypto_pump(void *u)
{
session *self = static_cast< session * >(u);
self->EncryptOutboundFrames();
self->DecryptInboundFrames();
}
void void
session::handle_verify_session_start(iwp_async_session_start *s) session::handle_verify_session_start(iwp_async_session_start *s)
{ {
@ -1829,7 +1998,7 @@ namespace iwp
link->timeout_job_id = 0; link->timeout_job_id = 0;
link->logic = logic; link->logic = logic;
// start cleanup timer // start cleanup timer
link->issue_cleanup_timer(2500); link->issue_cleanup_timer(1000);
return true; return true;
} }
@ -1854,8 +2023,8 @@ namespace iwp
iter.link = l; iter.link = l;
// TODO: race condition with cleanup timer // TODO: race condition with cleanup timer
for(auto &item : link->m_sessions) for(auto &item : link->m_sessions)
if(item.second.impl) if(item.second->impl)
if(!iter.visit(&iter, &item.second)) if(!iter.visit(&iter, item.second))
return; return;
} }
} }
@ -1933,6 +2102,7 @@ namespace iwp
delete link; delete link;
return; return;
} }
link->frame.alive();
link->serv->put_session(link->addr, link); link->serv->put_session(link->addr, link);
llarp::Debug("send introack to ", link->addr, " via ", link->serv->addr); llarp::Debug("send introack to ", link->addr, " via ", link->serv->addr);
if(llarp_ev_udp_sendto(link->udp, link->addr, i->buf, i->sz) == -1) if(llarp_ev_udp_sendto(link->udp, link->addr, i->buf, i->sz) == -1)

@ -55,8 +55,8 @@ struct llarp_nodedb
auto itr = this->entries.begin(); auto itr = this->entries.begin();
while(itr != this->entries.end()) while(itr != this->entries.end())
{ {
llarp::Info("Has byte_t [", test.size(), "] vs [", itr->first.size(), "]"); llarp::Info("Has byte_t [", test.size(), "] vs [", itr->first.size(),
if (memcmp(test.data(), itr->first.data(), 32) == 0) { "]"); if (memcmp(test.data(), itr->first.data(), 32) == 0) {
llarp::Info("Match"); llarp::Info("Match");
} }
itr++; itr++;
@ -198,7 +198,8 @@ struct llarp_nodedb
{ {
#if __APPLE__ && __MACH__ #if __APPLE__ && __MACH__
// skip .DS_Store files // skip .DS_Store files
if (strstr(fpath.c_str(), ".DS_Store") != 0) { if(strstr(fpath.c_str(), ".DS_Store") != 0)
{
return false; return false;
} }
#endif #endif
@ -218,7 +219,9 @@ struct llarp_nodedb
return true; return true;
} }
bool iterate(struct llarp_nodedb_iter i) { bool
iterate(struct llarp_nodedb_iter i)
{
i.index = 0; i.index = 0;
auto itr = entries.begin(); auto itr = entries.begin();
while(itr != entries.end()) while(itr != entries.end())
@ -372,12 +375,14 @@ llarp_nodedb_load_dir(struct llarp_nodedb *n, const char *dir)
} }
bool bool
llarp_nodedb_put_rc(struct llarp_nodedb *n, struct llarp_rc *rc) { llarp_nodedb_put_rc(struct llarp_nodedb *n, struct llarp_rc *rc)
{
return n->setRC(rc); return n->setRC(rc);
} }
int int
llarp_nodedb_iterate_all(struct llarp_nodedb *n, struct llarp_nodedb_iter i) { llarp_nodedb_iterate_all(struct llarp_nodedb *n, struct llarp_nodedb_iter i)
{
n->iterate(i); n->iterate(i);
return n->entries.size(); return n->entries.size();
} }

@ -2,9 +2,12 @@
#include <llarp/encrypted_frame.hpp> #include <llarp/encrypted_frame.hpp>
#include <llarp/path.hpp> #include <llarp/path.hpp>
#include "buffer.hpp" #include "buffer.hpp"
#include "pathbuilder.hpp"
#include "router.hpp" #include "router.hpp"
namespace llarp namespace llarp
{
namespace path
{ {
PathContext::PathContext(llarp_router* router) PathContext::PathContext(llarp_router* router)
: m_Router(router), m_AllowTransit(false) : m_Router(router), m_AllowTransit(false)
@ -70,16 +73,17 @@ namespace llarp
} }
return m_Router->SendToOrQueue(nextHop, msg); return m_Router->SendToOrQueue(nextHop, msg);
} }
template < typename Map_t, typename Key_t, typename CheckValue_t > template < typename Map_t, typename Key_t, typename CheckValue_t,
typename GetFunc_t >
IHopHandler* IHopHandler*
MapGet(Map_t& map, const Key_t& k, CheckValue_t check) MapGet(Map_t& map, const Key_t& k, CheckValue_t check, GetFunc_t get)
{ {
std::unique_lock< std::mutex > lock(map.first); std::unique_lock< std::mutex > lock(map.first);
auto range = map.second.equal_range(k); auto range = map.second.equal_range(k);
for(auto i = range.first; i != range.second; ++i) for(auto i = range.first; i != range.second; ++i)
{ {
if(check(i->second)) if(check(i->second))
return i->second; return get(i->second);
} }
return nullptr; return nullptr;
} }
@ -131,10 +135,11 @@ namespace llarp
} }
void void
PathContext::AddOwnPath(Path* path) PathContext::AddOwnPath(PathSet* set, Path* path)
{ {
MapPut(m_OurPaths, path->TXID(), path); set->AddPath(path);
MapPut(m_OurPaths, path->RXID(), path); MapPut(m_OurPaths, path->TXID(), set);
MapPut(m_OurPaths, path->RXID(), set);
} }
bool bool
@ -148,23 +153,32 @@ namespace llarp
IHopHandler* IHopHandler*
PathContext::GetByUpstream(const RouterID& remote, const PathID_t& id) PathContext::GetByUpstream(const RouterID& remote, const PathID_t& id)
{ {
auto own = MapGet(m_OurPaths, id, [remote](const Path* p) -> bool { auto own = MapGet(m_OurPaths, id,
return p->Upstream() == remote; [](const PathSet* s) -> bool {
// TODO: is this right?
return true;
},
[remote, id](PathSet* p) -> IHopHandler* {
return p->GetByUpstream(remote, id);
}); });
if(own) if(own)
return own; return own;
return MapGet(m_TransitPaths, id, [remote](const TransitHop* hop) -> bool { return MapGet(m_TransitPaths, id,
[remote](const TransitHop* hop) -> bool {
return hop->info.upstream == remote; return hop->info.upstream == remote;
}); },
[](TransitHop* h) -> IHopHandler* { return h; });
} }
IHopHandler* IHopHandler*
PathContext::GetByDownstream(const RouterID& remote, const PathID_t& id) PathContext::GetByDownstream(const RouterID& remote, const PathID_t& id)
{ {
return MapGet(m_TransitPaths, id, [remote](const TransitHop* hop) -> bool { return MapGet(m_TransitPaths, id,
[remote](const TransitHop* hop) -> bool {
return hop->info.downstream == remote; return hop->info.downstream == remote;
}); },
[](TransitHop* h) -> IHopHandler* { return h; });
} }
const byte_t* const byte_t*
@ -210,6 +224,38 @@ namespace llarp
map.erase(p->info.rxID); map.erase(p->info.rxID);
delete p; delete p;
} }
for(auto& builder : m_PathBuilders)
{
builder->ExpirePaths(now);
}
}
void
PathContext::BuildPaths()
{
for(auto& builder : m_PathBuilders)
{
if(builder->ShouldBuildMore())
{
builder->BuildOne();
}
}
}
void
PathContext::AddPathBuilder(llarp_pathbuilder_context* ctx)
{
m_PathBuilders.push_back(ctx);
}
PathHopConfig::PathHopConfig()
{
llarp_rc_clear(&router);
}
PathHopConfig::~PathHopConfig()
{
llarp_rc_free(&router);
} }
Path::Path(llarp_path_hops* h) : hops(h->numHops) Path::Path(llarp_path_hops* h) : hops(h->numHops)
@ -226,6 +272,12 @@ namespace llarp
} }
} }
void
Path::SetBuildResultHook(BuildResultHookFunc func)
{
m_BuiltHook = func;
}
const PathID_t& const PathID_t&
Path::TXID() const Path::TXID() const
{ {
@ -262,7 +314,12 @@ namespace llarp
bool bool
Path::Expired(llarp_time_t now) const Path::Expired(llarp_time_t now) const
{ {
if(status == ePathEstablished)
return now - buildStarted > hops[0].lifetime; return now - buildStarted > hops[0].lifetime;
else if(status == ePathBuilding)
return now - buildStarted > PATH_BUILD_TIMEOUT;
else
return true;
} }
bool bool
@ -295,7 +352,8 @@ namespace llarp
} }
bool bool
Path::SendRoutingMessage(const llarp::routing::IMessage* msg, llarp_router* r) Path::SendRoutingMessage(const llarp::routing::IMessage* msg,
llarp_router* r)
{ {
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);
@ -310,4 +368,37 @@ namespace llarp
return HandleUpstream(buf, N, r); return HandleUpstream(buf, N, r);
} }
bool
Path::HandlePathConfirmMessage(
const llarp::routing::PathConfirmMessage* msg)
{
if(status == ePathBuilding)
{
// confirm that we build the path
status = ePathEstablished;
if(m_BuiltHook)
m_BuiltHook(this);
m_BuiltHook = nullptr;
return true;
}
llarp::Warn("got unwarrented path confirm message on rx=", RXID(),
" tx=", TXID());
return false;
}
bool
Path::HandlePathLatencyMessage(
const llarp::routing::PathLatencyMessage* msg)
{
// TODO: implement me
return false;
}
bool
Path::HandleDHTMessage(const llarp::dht::IMessage* msg)
{
// TODO: implement me
return false;
}
} // namespace path
} // namespace llarp } // namespace llarp

@ -9,7 +9,10 @@ namespace llarp
template < typename User > template < typename User >
struct AsyncPathKeyExchangeContext struct AsyncPathKeyExchangeContext
{ {
Path* path = nullptr; typedef llarp::path::Path Path_t;
typedef llarp::path::PathSet PathSet_t;
PathSet_t* pathset = nullptr;
Path_t* path = nullptr;
typedef void (*Handler)(AsyncPathKeyExchangeContext< User >*); typedef void (*Handler)(AsyncPathKeyExchangeContext< User >*);
User* user = nullptr; User* user = nullptr;
Handler result = nullptr; Handler result = nullptr;
@ -105,8 +108,8 @@ namespace llarp
/// Generate all keys asynchronously and call hadler when done /// Generate all keys asynchronously and call hadler when done
void void
AsyncGenerateKeys(Path* p, llarp_logic* l, llarp_threadpool* pool, User* u, AsyncGenerateKeys(Path_t* p, llarp_logic* l, llarp_threadpool* pool,
Handler func) User* u, Handler func)
{ {
path = p; path = p;
logic = l; logic = l;
@ -124,16 +127,6 @@ namespace llarp
} }
}; };
PathHopConfig::PathHopConfig()
{
llarp_rc_clear(&router);
}
PathHopConfig::~PathHopConfig()
{
llarp_rc_free(&router);
}
void void
pathbuilder_generated_keys( pathbuilder_generated_keys(
AsyncPathKeyExchangeContext< llarp_pathbuild_job >* ctx) AsyncPathKeyExchangeContext< llarp_pathbuild_job >* ctx)
@ -146,8 +139,8 @@ namespace llarp
llarp::Error("failed to send LRCM"); llarp::Error("failed to send LRCM");
return; return;
} }
ctx->path->status = ePathBuilding; ctx->path->status = llarp::path::ePathBuilding;
router->paths.AddOwnPath(ctx->path); router->paths.AddOwnPath(ctx->pathset, ctx->path);
ctx->user->pathBuildStarted(ctx->user); ctx->user->pathBuildStarted(ctx->user);
} }
@ -171,16 +164,33 @@ namespace llarp
AsyncPathKeyExchangeContext< llarp_pathbuild_job >* ctx = AsyncPathKeyExchangeContext< llarp_pathbuild_job >* ctx =
new AsyncPathKeyExchangeContext< llarp_pathbuild_job >( new AsyncPathKeyExchangeContext< llarp_pathbuild_job >(
&job->router->crypto); &job->router->crypto);
ctx->pathset = job->context;
ctx->AsyncGenerateKeys(new Path(&job->hops), job->router->logic, auto path = new llarp::path::Path(&job->hops);
job->router->tp, job, &pathbuilder_generated_keys); path->SetBuildResultHook(std::bind(&llarp::path::PathSet::HandlePathBuilt,
ctx->pathset, std::placeholders::_1));
ctx->AsyncGenerateKeys(path, job->router->logic, job->router->tp, job,
&pathbuilder_generated_keys);
} }
} // namespace llarp } // namespace llarp
llarp_pathbuilder_context::llarp_pathbuilder_context( llarp_pathbuilder_context::llarp_pathbuilder_context(
llarp_router* p_router, struct llarp_dht_context* p_dht) llarp_router* p_router, struct llarp_dht_context* p_dht)
: router(p_router), dht(p_dht) // TODO: hardcoded value
: llarp::path::PathSet(4), router(p_router), dht(p_dht)
{ {
p_router->paths.AddPathBuilder(this);
}
void
llarp_pathbuilder_context::BuildOne()
{
llarp_pathbuild_job* job = new llarp_pathbuild_job;
job->context = this;
job->selectHop = nullptr;
job->hops.numHops = 4;
job->user = nullptr;
job->pathBuildStarted = [](llarp_pathbuild_job* j) { delete j; };
llarp_pathbuilder_build_path(job);
} }
extern "C" { extern "C" {

@ -2,13 +2,16 @@
#define LLARP_PATHFINDER_HPP_ #define LLARP_PATHFINDER_HPP_
#include <llarp/pathbuilder.h> #include <llarp/pathbuilder.h>
struct llarp_pathbuilder_context struct llarp_pathbuilder_context : public llarp::path::PathSet
{ {
struct llarp_router* router; struct llarp_router* router;
struct llarp_dht_context* dht; struct llarp_dht_context* dht;
/// copy cstr /// construct
llarp_pathbuilder_context(llarp_router* p_router, llarp_pathbuilder_context(llarp_router* p_router,
struct llarp_dht_context* p_dht); struct llarp_dht_context* p_dht);
void
BuildOne();
}; };
#endif #endif

@ -0,0 +1,97 @@
#include <llarp/path.hpp>
#include <llarp/pathset.hpp>
namespace llarp
{
namespace path
{
PathSet::PathSet(size_t num) : m_NumPaths(num)
{
}
bool
PathSet::ShouldBuildMore() const
{
return std::get< 0 >(m_Paths).size() < m_NumPaths;
}
void
PathSet::ExpirePaths(llarp_time_t now)
{
{
auto& map = std::get< 0 >(m_Paths);
auto itr = map.begin();
while(itr != map.end())
{
if(itr->second->Expired(now))
{
itr = map.erase(itr);
}
}
}
{
auto& map = std::get< 1 >(m_Paths);
auto itr = map.begin();
while(itr != map.end())
{
if(itr->second->Expired(now))
{
// delete path on second iteration
delete itr->second;
itr = map.erase(itr);
}
}
}
}
size_t
PathSet::NumInStatus(PathStatus st) const
{
size_t count = 0;
auto& map = std::get< 0 >(m_Paths);
auto itr = map.begin();
while(itr != map.end())
{
if(itr->second->status == st)
++count;
++itr;
}
return count;
}
void
PathSet::AddPath(Path* path)
{
std::get< 0 >(m_Paths).emplace(path->TXID(), path);
std::get< 1 >(m_Paths).emplace(path->RXID(), path);
}
void
PathSet::RemovePath(Path* path)
{
std::get< 0 >(m_Paths).erase(path->TXID());
std::get< 1 >(m_Paths).erase(path->RXID());
}
Path*
PathSet::GetByUpstream(const RouterID& remote, const PathID_t& rxid)
{
auto& set = std::get< 1 >(m_Paths);
auto itr = set.begin();
while(itr != set.end())
{
if(itr->second->Upstream() == remote)
return itr->second;
++itr;
}
return nullptr;
}
void
PathSet::HandlePathBuilt(Path* path)
{
// TODO: implement me
}
} // namespace path
} // namespace llarp

@ -155,18 +155,20 @@ namespace llarp
struct LRCMFrameDecrypt struct LRCMFrameDecrypt
{ {
typedef llarp::path::PathContext Context;
typedef llarp::path::TransitHop Hop;
typedef AsyncFrameDecrypter< LRCMFrameDecrypt > Decrypter; typedef AsyncFrameDecrypter< LRCMFrameDecrypt > Decrypter;
Decrypter* decrypter; Decrypter* decrypter;
std::deque< EncryptedFrame > frames; std::deque< EncryptedFrame > frames;
PathContext* context; Context* context;
// decrypted record // decrypted record
LR_CommitRecord record; LR_CommitRecord record;
// the actual hop // the actual hop
TransitHop* hop; Hop* hop;
LRCMFrameDecrypt(PathContext* ctx, Decrypter* dec, LRCMFrameDecrypt(Context* ctx, Decrypter* dec,
const LR_CommitMessage* commit) const LR_CommitMessage* commit)
: decrypter(dec), context(ctx), hop(new TransitHop) : decrypter(dec), context(ctx), hop(new Hop)
{ {
for(const auto& f : commit->frames) for(const auto& f : commit->frames)
frames.push_back(f); frames.push_back(f);
@ -276,7 +278,7 @@ namespace llarp
}; };
bool bool
LR_CommitMessage::AsyncDecrypt(PathContext* context) const LR_CommitMessage::AsyncDecrypt(llarp::path::PathContext* context) const
{ {
LRCMFrameDecrypt::Decrypter* decrypter = new LRCMFrameDecrypt::Decrypter( LRCMFrameDecrypt::Decrypter* decrypter = new LRCMFrameDecrypt::Decrypter(
context->Crypto(), context->EncryptionSecretKey(), context->Crypto(), context->EncryptionSecretKey(),

@ -356,6 +356,7 @@ llarp_router::HandleExploritoryPathBuildStarted(llarp_pathbuild_job *job)
delete job; delete job;
} }
// TODO: do we still need this?
void void
llarp_router::BuildExploritoryPath() llarp_router::BuildExploritoryPath()
{ {
@ -379,7 +380,7 @@ llarp_router::Tick()
auto N = llarp_nodedb_num_loaded(nodedb); auto N = llarp_nodedb_num_loaded(nodedb);
if(N > 5) if(N > 5)
{ {
BuildExploritoryPath(); paths.BuildPaths();
} }
else else
{ {
@ -596,15 +597,13 @@ llarp_router::Run()
llarp_rc_set_pubenckey(&rc, llarp::seckey_topublic(encryption)); llarp_rc_set_pubenckey(&rc, llarp::seckey_topublic(encryption));
char ftmp[68] = {0}; char ftmp[68] = {0};
const char *hexKey = llarp::HexEncode< llarp::PubKey, const char *hexKey = llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(
decltype(ftmp) >(llarp::seckey_topublic(encryption), llarp::seckey_topublic(encryption), ftmp);
ftmp);
llarp::Info("Your Encryption pubkey ", hexKey); llarp::Info("Your Encryption pubkey ", hexKey);
// set public signing key // set public signing key
llarp_rc_set_pubsigkey(&rc, llarp::seckey_topublic(identity)); llarp_rc_set_pubsigkey(&rc, llarp::seckey_topublic(identity));
hexKey = llarp::HexEncode< llarp::PubKey, hexKey = llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(
decltype(ftmp) >(llarp::seckey_topublic(identity), llarp::seckey_topublic(identity), ftmp);
ftmp);
llarp::Info("Your Identity pubkey ", hexKey); llarp::Info("Your Identity pubkey ", hexKey);
llarp_rc_sign(&crypto, identity, &rc); llarp_rc_sign(&crypto, identity, &rc);
@ -641,14 +640,16 @@ llarp_router::Run()
// immediate connect all for service node // immediate connect all for service node
uint64_t delay = rand() % 100; uint64_t delay = rand() % 100;
llarp_logic_call_later(logic, {delay, this, &ConnectAll}); llarp_logic_call_later(logic, {delay, this, &ConnectAll});
//llarp_logic_call_later(logic, {static_cast<uint64_t>(delay), this, &ConnectAll}); // llarp_logic_call_later(logic, {static_cast<uint64_t>(delay), this,
// &ConnectAll});
} }
else else
{ {
// delayed connect all for clients // delayed connect all for clients
uint64_t delay = ((rand() % 10) * 500) + 1000; uint64_t delay = ((rand() % 10) * 500) + 1000;
llarp_logic_call_later(logic, {delay, this, &ConnectAll}); llarp_logic_call_later(logic, {delay, this, &ConnectAll});
//llarp_logic_call_later(logic, {static_cast<uint64_t>(delay), this, &ConnectAll}); // llarp_logic_call_later(logic, {static_cast<uint64_t>(delay), this,
// &ConnectAll});
} }
llarp::PubKey ourPubkey = pubkey(); llarp::PubKey ourPubkey = pubkey();

@ -58,7 +58,7 @@ struct llarp_router
llarp_threadpool *tp; llarp_threadpool *tp;
llarp_logic *logic; llarp_logic *logic;
llarp_crypto crypto; llarp_crypto crypto;
llarp::PathContext paths; llarp::path::PathContext paths;
llarp::SecretKey identity; llarp::SecretKey identity;
llarp::SecretKey encryption; llarp::SecretKey encryption;
llarp_threadpool *disk; llarp_threadpool *disk;

@ -44,9 +44,7 @@ namespace llarp
bool bool
PathConfirmMessage::HandleMessage(IMessageHandler* h) const PathConfirmMessage::HandleMessage(IMessageHandler* h) const
{ {
llarp::Info("got path confirm created=", pathCreated, return h && h->HandlePathConfirmMessage(this);
" lifetime=", pathLifetime);
return true;
} }
} // namespace routing } // namespace routing

@ -3,6 +3,8 @@
#include "router.hpp" #include "router.hpp"
namespace llarp namespace llarp
{
namespace path
{ {
bool bool
TransitHop::Expired(llarp_time_t now) const TransitHop::Expired(llarp_time_t now) const
@ -84,5 +86,5 @@ namespace llarp
info.downstream, " to ", info.upstream); info.downstream, " to ", info.upstream);
return r->SendToOrQueue(info.upstream, msg); return r->SendToOrQueue(info.upstream, msg);
} }
} // namespace path
} // namespace llarp } // namespace llarp

Loading…
Cancel
Save