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

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

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

@ -59,14 +59,14 @@ shadow: shadow-build
bash -c "$(SHADOW_BIN) -w $$(cat /proc/cpuinfo | grep processor | wc -l) $(SHADOW_CONFIG) &> $(SHADOW_LOG) || true"
testnet-configure: clean
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug
testnet-build: testnet-configure
ninja
testnet: testnet-build
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)
test: debug-configure

@ -21,21 +21,22 @@ handle_signal(int sig)
#include <llarp/router_contact.h>
#include <llarp/time.h>
#include <fstream>
#include "fs.hpp"
#include "buffer.hpp"
#include "crypto.hpp"
#include "fs.hpp"
#include "router.hpp"
bool printNode(struct llarp_nodedb_iter *iter) {
bool
printNode(struct llarp_nodedb_iter *iter)
{
char ftmp[68] = {0};
const char *hexname =
llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(iter->rc->pubkey, ftmp);
llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(iter->rc->pubkey, ftmp);
printf("[%zu]=>[%s]\n", iter->index, hexname);
return false;
}
int
main(int argc, char *argv[])
{
@ -61,9 +62,9 @@ main(int argc, char *argv[])
"\n");
return 0;
}
bool genMode = false;
bool updMode = false;
bool listMode = false;
bool genMode = false;
bool updMode = false;
bool listMode = false;
bool importMode = false;
bool exportMode = false;
int c;
@ -71,8 +72,8 @@ main(int argc, char *argv[])
char defaultConfName[] = "daemon.ini";
conffname = defaultConfName;
char *rcfname;
char defaultRcName[] = "other.signed";
rcfname = defaultRcName;
char defaultRcName[] = "other.signed";
rcfname = defaultRcName;
bool haveRequiredOptions = false;
while(1)
{
@ -97,49 +98,51 @@ main(int argc, char *argv[])
break;
case 'l':
haveRequiredOptions = true;
listMode = true;
listMode = true;
break;
case 'i':
// printf ("option -g with value `%s'\n", optarg);
rcfname = optarg;
rcfname = optarg;
haveRequiredOptions = true;
importMode = true;
importMode = true;
break;
case 'e':
// printf ("option -g with value `%s'\n", optarg);
rcfname = optarg;
rcfname = optarg;
haveRequiredOptions = true;
exportMode = true;
exportMode = true;
break;
case 'g':
// printf ("option -g with value `%s'\n", optarg);
rcfname = optarg;
rcfname = optarg;
haveRequiredOptions = true;
genMode = true;
genMode = true;
break;
case 'u':
// printf ("option -u with value `%s'\n", optarg);
rcfname = optarg;
rcfname = optarg;
haveRequiredOptions = true;
updMode = true;
updMode = true;
break;
default:
abort();
}
}
if (!haveRequiredOptions) {
if(!haveRequiredOptions)
{
llarp::Error("Parameters dont all have their required parameters.\n");
return 0;
}
printf("parsed options\n");
if(!genMode && !updMode && !listMode &&!importMode && !exportMode)
if(!genMode && !updMode && !listMode && !importMode && !exportMode)
{
llarp::Error("I don't know what to do, no generate or update parameter\n");
return 0;
}
ctx = llarp_main_init(conffname, !TESTNET);
if (!ctx) {
if(!ctx)
{
llarp::Error("Cant set up context");
return 0;
}
@ -162,10 +165,12 @@ main(int argc, char *argv[])
llarp_crypto 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";
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));
// get identity public sig key
@ -206,33 +211,37 @@ main(int argc, char *argv[])
// write file
llarp_rc_write(&tmp, our_rc_file_out.c_str());
}
if (listMode) {
if(listMode)
{
llarp_main_loadDatabase(ctx);
llarp_nodedb_iter iter;
iter.visit = printNode;
llarp_main_iterateDatabase(ctx, iter);
}
if (importMode) {
if(importMode)
{
llarp_main_loadDatabase(ctx);
llarp::Info("Loading ", rcfname);
llarp_rc *rc = llarp_rc_read(rcfname);
if (!rc)
if(!rc)
{
llarp::Error("Can't load RC");
return 0;
}
llarp_main_putDatabase(ctx, rc);
}
if (exportMode) {
if(exportMode)
{
llarp_main_loadDatabase(ctx);
//llarp::Info("Looking for string: ", rcfname);
// llarp::Info("Looking for string: ", rcfname);
llarp::PubKey binaryPK;
llarp::HexDecode(rcfname, binaryPK.data());
llarp::Info("Looking for binary: ", binaryPK);
struct llarp_rc *rc = llarp_main_getDatabase(ctx, binaryPK.data());
if (!rc) {
if(!rc)
{
llarp::Error("Can't load RC from database");
}
std::string filename(rcfname);
@ -241,5 +250,5 @@ main(int argc, char *argv[])
llarp_rc_write(rc, filename.c_str());
}
llarp_main_free(ctx);
return 1; // success
return 1; // success
}

@ -39,7 +39,6 @@ llarp_main_loadDatabase(struct llarp_main *ptr);
int
llarp_main_iterateDatabase(struct llarp_main *ptr, struct llarp_nodedb_iter i);
/// put RC into nodeDB
bool
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 *
llarp_main_getDatabase(struct llarp_main *ptr, byte_t *pk);
void
llarp_main_free(struct llarp_main *ptr);

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

@ -4,6 +4,7 @@
#include <llarp/ev.h>
#include <llarp/logic.h>
#include <llarp/threadpool.h>
#include <llarp/time.h>
/**
* crypto_async.h
@ -166,6 +167,8 @@ struct iwp_async_frame
{
/// true if decryption succeded
bool success;
/// timestamp for CoDel
llarp_time_t created;
struct llarp_async_iwp *iwp;
/// a pointer to pass ourself
void *user;
@ -179,6 +182,14 @@ struct iwp_async_frame
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
void
iwp_call_async_frame_decrypt(struct llarp_async_iwp *iwp,

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

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

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

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

@ -5,10 +5,12 @@
#include <llarp/time.h>
#include <llarp/aligned.hpp>
#include <llarp/crypto.hpp>
#include <llarp/dht.hpp>
#include <llarp/endpoint.hpp>
#include <llarp/messages/relay.hpp>
#include <llarp/messages/relay_commit.hpp>
#include <llarp/path_types.hpp>
#include <llarp/pathset.hpp>
#include <llarp/router_id.hpp>
#include <llarp/routing/handler.hpp>
#include <llarp/routing/message.hpp>
@ -19,292 +21,315 @@
#include <unordered_map>
#include <vector>
#define DEFAULT_PATH_LIFETIME (10 * 60 * 1000)
namespace llarp
{
struct TransitHopInfo
namespace path
{
TransitHopInfo() = default;
TransitHopInfo(const TransitHopInfo& other);
TransitHopInfo(const RouterID& down, const LR_CommitRecord& record);
struct TransitHopInfo
{
TransitHopInfo() = default;
TransitHopInfo(const TransitHopInfo& other);
TransitHopInfo(const RouterID& down, const LR_CommitRecord& record);
PathID_t txID, rxID;
RouterID upstream;
RouterID downstream;
PathID_t txID, rxID;
RouterID upstream;
RouterID downstream;
friend std::ostream&
operator<<(std::ostream& out, const TransitHopInfo& info)
{
out << "<tx=" << info.txID << " rx=" << info.rxID;
out << " upstream=" << info.upstream << " downstream=" << info.downstream;
return out << ">";
}
friend std::ostream&
operator<<(std::ostream& out, const TransitHopInfo& info)
{
out << "<tx=" << info.txID << " rx=" << info.rxID;
out << " upstream=" << info.upstream
<< " downstream=" << info.downstream;
return out << ">";
}
bool
operator==(const TransitHopInfo& other) const
{
return txID == other.txID && rxID == other.rxID
&& upstream == other.upstream && downstream == other.downstream;
}
bool
operator==(const TransitHopInfo& other) const
{
return txID == other.txID && rxID == other.rxID
&& upstream == other.upstream && downstream == other.downstream;
}
bool
operator!=(const TransitHopInfo& other) const
{
return !(*this == other);
}
bool
operator!=(const TransitHopInfo& other) const
{
return !(*this == other);
}
bool
operator<(const TransitHopInfo& other) const
{
return txID < other.txID || rxID < other.rxID || upstream < other.upstream
|| downstream < other.downstream;
}
bool
operator<(const TransitHopInfo& other) const
{
return txID < other.txID || rxID < other.rxID
|| upstream < other.upstream || downstream < other.downstream;
}
struct Hash
{
std::size_t
operator()(TransitHopInfo const& a) const
{
std::size_t idx0, idx1, idx2, idx3;
memcpy(&idx0, a.upstream, sizeof(std::size_t));
memcpy(&idx1, a.downstream, sizeof(std::size_t));
memcpy(&idx2, a.txID, sizeof(std::size_t));
memcpy(&idx3, a.rxID, sizeof(std::size_t));
return idx0 ^ idx1 ^ idx2;
}
};
};
struct Hash
struct PathIDHash
{
std::size_t
operator()(TransitHopInfo const& a) const
operator()(const PathID_t& a) const
{
std::size_t idx0, idx1, idx2, idx3;
memcpy(&idx0, a.upstream, sizeof(std::size_t));
memcpy(&idx1, a.downstream, sizeof(std::size_t));
memcpy(&idx2, a.txID, sizeof(std::size_t));
memcpy(&idx3, a.rxID, sizeof(std::size_t));
return idx0 ^ idx1 ^ idx2;
std::size_t idx0;
memcpy(&idx0, a, sizeof(std::size_t));
return idx0;
}
};
};
struct PathIDHash
{
std::size_t
operator()(const PathID_t& a) const
struct IHopHandler
{
std::size_t idx0;
memcpy(&idx0, a, sizeof(std::size_t));
return idx0;
}
};
virtual ~IHopHandler(){};
struct IHopHandler
{
virtual ~IHopHandler(){};
virtual bool
Expired(llarp_time_t now) const = 0;
virtual bool
SendRoutingMessage(const llarp::routing::IMessage* msg,
llarp_router* r) = 0;
virtual bool
Expired(llarp_time_t now) const = 0;
// handle data in upstream direction
virtual bool
HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y,
llarp_router* r) = 0;
virtual bool
SendRoutingMessage(const llarp::routing::IMessage* msg,
// handle data in downstream direction
virtual bool
HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y,
llarp_router* r) = 0;
};
// handle data in upstream direction
virtual bool
HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r) = 0;
struct TransitHop : public IHopHandler
{
TransitHop() = default;
// handle data in downstream direction
virtual bool
HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y,
llarp_router* r) = 0;
};
TransitHop(const TransitHop& other);
struct TransitHop : public IHopHandler
{
TransitHop() = default;
TransitHopInfo info;
SharedSecret pathKey;
llarp_time_t started = 0;
// 10 minutes default
llarp_time_t lifetime = DEFAULT_PATH_LIFETIME;
llarp_proto_version_t version;
friend std::ostream&
operator<<(std::ostream& out, const TransitHop& h)
{
return out << "[TransitHop " << h.info << " started=" << h.started
<< " lifetime=" << h.lifetime << "]";
}
bool
Expired(llarp_time_t now) const;
TransitHop(const TransitHop& other);
bool
SendRoutingMessage(const llarp::routing::IMessage* msg, llarp_router* r);
TransitHopInfo info;
SharedSecret pathKey;
llarp_time_t started = 0;
// 10 minutes default
llarp_time_t lifetime = DEFAULT_PATH_LIFETIME;
llarp_proto_version_t version;
// handle data in upstream direction
bool
HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r);
friend std::ostream&
operator<<(std::ostream& out, const TransitHop& h)
// handle data in downstream direction
bool
HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r);
};
/// configuration for a single hop when building a path
struct PathHopConfig
{
return out << "[TransitHop " << h.info << " started=" << h.started
<< " lifetime=" << h.lifetime << "]";
}
/// path id
PathID_t txID, rxID;
// router contact of router
llarp_rc router;
// temp public encryption key
SecretKey commkey;
/// shared secret at this hop
SharedSecret shared;
/// next hop's router id
RouterID upstream;
/// nonce for key exchange
TunnelNonce nonce;
// lifetime
llarp_time_t lifetime = DEFAULT_PATH_LIFETIME;
~PathHopConfig();
PathHopConfig();
};
bool
Expired(llarp_time_t now) const;
/// A path we made
struct Path : public IHopHandler, public llarp::routing::IMessageHandler
{
typedef std::function< void(Path*) > BuildResultHookFunc;
typedef std::vector< PathHopConfig > HopList;
HopList hops;
llarp_time_t buildStarted;
PathStatus status;
bool
SendRoutingMessage(const llarp::routing::IMessage* msg, llarp_router* r);
Path(llarp_path_hops* path);
// handle data in upstream direction
bool
HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r);
void
SetBuildResultHook(BuildResultHookFunc func);
// handle data in downstream direction
bool
HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r);
};
bool
Expired(llarp_time_t now) const;
/// configuration for a single hop when building a path
struct PathHopConfig
{
/// path id
PathID_t txID, rxID;
// router contact of router
llarp_rc router;
// temp public encryption key
SecretKey commkey;
/// shared secret at this hop
SharedSecret shared;
/// next hop's router id
RouterID upstream;
/// nonce for key exchange
TunnelNonce nonce;
// lifetime
llarp_time_t lifetime = DEFAULT_PATH_LIFETIME;
~PathHopConfig();
PathHopConfig();
};
enum PathStatus
{
ePathBuilding,
ePathEstablished,
ePathTimeout,
ePathExpired
};
/// A path we made
struct Path : public IHopHandler, public llarp::routing::IMessageHandler
{
typedef std::vector< PathHopConfig > HopList;
HopList hops;
llarp_time_t buildStarted;
PathStatus status;
bool
SendRoutingMessage(const llarp::routing::IMessage* msg, llarp_router* r);
Path(llarp_path_hops* path);
bool
HandlePathConfirmMessage(const llarp::routing::PathConfirmMessage* msg);
bool
Expired(llarp_time_t now) const;
bool
HandlePathLatencyMessage(const llarp::routing::PathLatencyMessage* msg);
bool
SendRoutingMessage(const llarp::routing::IMessage* msg, llarp_router* r);
bool
HandleDHTMessage(const llarp::dht::IMessage* msg);
bool
HandleRoutingMessage(llarp_buffer_t buf, llarp_router* r);
bool
HandleRoutingMessage(llarp_buffer_t buf, llarp_router* r);
bool
HandleHiddenServiceData(llarp_buffer_t buf);
bool
HandleHiddenServiceData(llarp_buffer_t buf);
// handle data in upstream direction
bool
HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r);
// handle data in upstream direction
bool
HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r);
// handle data in downstream direction
bool
HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r);
// handle data in downstream direction
bool
HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r);
// Is this deprecated?
const PathID_t&
TXID() const;
// Is this deprecated?
// nope not deprecated :^DDDD
const PathID_t&
TXID() const;
const PathID_t&
RXID() const;
const PathID_t&
RXID() const;
RouterID
Upstream() const;
RouterID
Upstream() const;
protected:
llarp::routing::InboundMessageParser m_InboundMessageParser;
};
protected:
llarp::routing::InboundMessageParser m_InboundMessageParser;
enum PathBuildStatus
{
ePathBuildSuccess,
ePathBuildTimeout,
ePathBuildReject
};
private:
BuildResultHookFunc m_BuiltHook;
};
struct PathContext
{
PathContext(llarp_router* router);
~PathContext();
enum PathBuildStatus
{
ePathBuildSuccess,
ePathBuildTimeout,
ePathBuildReject
};
struct PathContext
{
PathContext(llarp_router* router);
~PathContext();
/// called from router tick function
void
ExpirePaths();
/// called from router tick function
void
ExpirePaths();
void
AllowTransit();
void
RejectTransit();
/// called from router tick function
/// builds all paths we need to build at current tick
void
BuildPaths();
bool
AllowingTransit() const;
/// track a path builder with this context
void
AddPathBuilder(llarp_pathbuilder_context* set);
bool
HasTransitHop(const TransitHopInfo& info);
void
AllowTransit();
void
RejectTransit();
bool
HandleRelayCommit(const LR_CommitMessage* msg);
bool
AllowingTransit() const;
void
PutTransitHop(TransitHop* hop);
bool
HasTransitHop(const TransitHopInfo& info);
IHopHandler*
GetByUpstream(const RouterID& id, const PathID_t& path);
bool
HandleRelayCommit(const LR_CommitMessage* msg);
IHopHandler*
GetByDownstream(const RouterID& id, const PathID_t& path);
void
PutTransitHop(TransitHop* hop);
bool
ForwardLRCM(const RouterID& nextHop, std::deque< EncryptedFrame >& frames);
IHopHandler*
GetByUpstream(const RouterID& id, const PathID_t& path);
bool
HopIsUs(const PubKey& k) const;
IHopHandler*
GetByDownstream(const RouterID& id, const PathID_t& path);
bool
HandleLRUM(const RelayUpstreamMessage* msg);
bool
ForwardLRCM(const RouterID& nextHop,
std::deque< EncryptedFrame >& frames);
bool
HandleLRDM(const RelayDownstreamMessage* msg);
bool
HopIsUs(const PubKey& k) const;
void
AddOwnPath(Path* p);
bool
HandleLRUM(const RelayUpstreamMessage* msg);
typedef std::multimap< PathID_t, TransitHop* > TransitHopsMap_t;
bool
HandleLRDM(const RelayDownstreamMessage* msg);
typedef std::pair< std::mutex, TransitHopsMap_t > SyncTransitMap_t;
void
AddOwnPath(PathSet* set, Path* p);
typedef std::map< PathID_t, Path* > OwnedPathsMap_t;
typedef std::multimap< PathID_t, TransitHop* > TransitHopsMap_t;
typedef std::pair< std::mutex, OwnedPathsMap_t > SyncOwnedPathsMap_t;
typedef std::pair< std::mutex, TransitHopsMap_t > SyncTransitMap_t;
llarp_threadpool*
Worker();
// maps path id -> pathset owner of path
typedef std::map< PathID_t, PathSet* > OwnedPathsMap_t;
llarp_crypto*
Crypto();
typedef std::pair< std::mutex, OwnedPathsMap_t > SyncOwnedPathsMap_t;
llarp_logic*
Logic();
llarp_threadpool*
Worker();
llarp_router*
Router();
llarp_crypto*
Crypto();
byte_t*
EncryptionSecretKey();
llarp_logic*
Logic();
const byte_t*
OurRouterID() const;
llarp_router*
Router();
private:
llarp_router* m_Router;
SyncTransitMap_t m_TransitPaths;
SyncTransitMap_t m_Paths;
SyncOwnedPathsMap_t m_OurPaths;
byte_t*
EncryptionSecretKey();
bool m_AllowTransit;
};
const byte_t*
OurRouterID() const;
private:
llarp_router* m_Router;
SyncTransitMap_t m_TransitPaths;
SyncTransitMap_t m_Paths;
SyncOwnedPathsMap_t m_OurPaths;
std::list< llarp_pathbuilder_context* > m_PathBuilders;
bool m_AllowTransit;
};
} // namespace path
} // namespace llarp
#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
#include <llarp/buffer.h>
#include <llarp/dht.hpp>
#include <llarp/messages/path_confirm.hpp>
#include <llarp/messages/path_latency.hpp>
namespace llarp
{
@ -12,6 +15,15 @@ namespace llarp
{
virtual bool
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 llarp

@ -7,7 +7,6 @@ namespace llarp
{
namespace api
{
bool
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

@ -29,7 +29,7 @@ namespace llarp
bool
Context::ReloadConfig()
{
//llarp::Info("loading config at ", configfile);
// llarp::Info("loading config at ", configfile);
if(llarp_load_config(config, configfile.c_str()))
{
llarp_free_config(&config);
@ -94,7 +94,7 @@ namespace llarp
llarp::Error("nodedb_dir is incorrect");
return 0;
}
//llarp::Info("nodedb_dir [", nodedb_dir, "] configured!");
// llarp::Info("nodedb_dir [", nodedb_dir, "] configured!");
ssize_t loaded = llarp_nodedb_load_dir(nodedb, nodedb_dir);
llarp::Info("nodedb_dir loaded ", loaded, " RCs from [", nodedb_dir, "]");
if(loaded < 0)

@ -333,30 +333,7 @@ namespace iwp
hmac_then_decrypt(void *user)
{
iwp_async_frame *frame = static_cast< iwp_async_frame * >(user);
auto crypto = frame->iwp->crypto;
byte_t *hmac = frame->buf;
byte_t *nonce = frame->buf + 32;
byte_t *body = frame->buf + 64;
llarp::ShortHash digest;
llarp_buffer_t buf;
buf.base = nonce;
buf.cur = buf.base;
buf.sz = frame->sz - 32;
// h = MDS(n + x, S)
crypto->hmac(digest, buf, frame->sessionkey);
// check hmac
frame->success = memcmp(digest, hmac, 32) == 0;
// x = SE(S, p, n[0:24])
buf.base = body;
buf.cur = buf.base;
buf.sz = frame->sz - 64;
crypto->xchacha20(buf, frame->sessionkey, nonce);
// call result RIGHT HERE
// frame->hook(frame);
// delete frame;
iwp_decrypt_frame(frame);
// inform result
llarp_logic_queue_job(frame->iwp->logic, {frame, &inform_frame_done});
}
@ -365,25 +342,7 @@ namespace iwp
encrypt_then_hmac(void *user)
{
iwp_async_frame *frame = static_cast< iwp_async_frame * >(user);
auto crypto = frame->iwp->crypto;
byte_t *hmac = frame->buf;
byte_t *nonce = frame->buf + 32;
byte_t *body = frame->buf + 64;
llarp_buffer_t buf;
buf.base = body;
buf.cur = buf.base;
buf.sz = frame->sz - 64;
// randomize N
crypto->randbytes(nonce, 32);
// x = SE(S, p, n[0:24])
crypto->xchacha20(buf, frame->sessionkey, nonce);
// h = MDS(n + x, S)
buf.base = nonce;
buf.cur = buf.base;
buf.sz = frame->sz - 32;
crypto->hmac(hmac, buf, frame->sessionkey);
iwp_encrypt_frame(frame);
// call result RIGHT HERE
frame->hook(frame);
delete frame;
@ -399,6 +358,58 @@ iwp_call_async_keygen(struct llarp_async_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;
byte_t *hmac = frame->buf;
byte_t *nonce = frame->buf + 32;
byte_t *body = frame->buf + 64;
llarp::ShortHash digest;
llarp_buffer_t buf;
buf.base = nonce;
buf.cur = buf.base;
buf.sz = frame->sz - 32;
// h = MDS(n + x, S)
crypto->hmac(digest, buf, frame->sessionkey);
// check hmac
frame->success = memcmp(digest, hmac, 32) == 0;
// x = SE(S, p, n[0:24])
buf.base = body;
buf.cur = buf.base;
buf.sz = frame->sz - 64;
crypto->xchacha20(buf, frame->sessionkey, nonce);
return frame->success;
}
bool
iwp_encrypt_frame(struct iwp_async_frame *frame)
{
auto crypto = frame->iwp->crypto;
byte_t *hmac = frame->buf;
byte_t *nonce = frame->buf + 32;
byte_t *body = frame->buf + 64;
llarp_buffer_t buf;
buf.base = body;
buf.cur = buf.base;
buf.sz = frame->sz - 64;
// randomize N
crypto->randbytes(nonce, 32);
// x = SE(S, p, n[0:24])
crypto->xchacha20(buf, frame->sessionkey, nonce);
// h = MDS(n + x, S)
buf.base = nonce;
buf.cur = buf.base;
buf.sz = frame->sz - 32;
crypto->hmac(hmac, buf, frame->sessionkey);
return true;
}
void
iwp_call_async_gen_intro(struct llarp_async_iwp *iwp,
struct iwp_async_intro *intro)

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

@ -3,8 +3,8 @@
namespace llarp
{
int char2int(char input)
int
char2int(char input)
{
if(input >= '0' && input <= '9')
return input - '0';
@ -15,13 +15,13 @@ namespace llarp
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])
{
*(target++) = char2int(*src)*16 + char2int(src[1]);
*(target++) = char2int(*src) * 16 + char2int(src[1]);
src += 2;
}
}
}

@ -4,6 +4,7 @@
#include <llarp/time.h>
#include <llarp/crypto.hpp>
#include "address_info.hpp"
#include "codel.hpp"
#include "link/encoder.hpp"
#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
{
llarp_udp_io *udp;
@ -676,9 +687,22 @@ namespace iwp
llarp_link_establish_job *establish_job = nullptr;
/// cached timestamp for frame creation
llarp_time_t now;
uint32_t establish_job_id = 0;
uint32_t frames = 0;
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;
iwp_async_intro intro;
iwp_async_introack introack;
@ -770,21 +794,50 @@ namespace iwp
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
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;
while(frame.next_frame(&buf))
{
encrypt_frame_async_send(buf.base, buf.sz);
frame.pop_next_frame();
}
PumpCrypto();
}
// this is called from net thread
void
recv(const void *buf, size_t sz)
{
now = llarp_time_now_ms();
switch(state)
{
case eInitial:
@ -832,9 +885,11 @@ namespace iwp
crypto->shorthash(digest, buf);
auto id = frame.txids++;
auto msg = new transit_message(buf, digest, id);
// enter state
EnterState(eLIMSent);
// put into outbound send queue
add_outbound_message(id, msg);
EnterState(eLIMSent);
}
else
llarp::Error("LIM Encode failed");
@ -845,43 +900,10 @@ namespace iwp
// return true if we should be removed
bool
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);
Tick(uint64_t now);
// pump frames
if(state == eEstablished)
{
frame.retransmit();
pump();
}
// TODO: determine if we are too idle
return false;
}
static void
codel_timer_handler(void *user, uint64_t orig, uint64_t left);
bool
IsEstablished()
@ -1001,13 +1023,11 @@ namespace iwp
{
session *self = static_cast< session * >(frame->user);
llarp::Debug("rx ", frame->sz, " frames=", self->frames);
self->frames--;
if(frame->success)
{
if(self->frame.process(frame->buf + 64, frame->sz - 64))
{
self->frame.alive();
self->pump();
}
else
llarp::Error("invalid frame from ", self->addr);
@ -1021,14 +1041,38 @@ namespace iwp
{
if(sz > 64)
{
iwp_async_frame *frame = alloc_frame(buf, sz);
frame->hook = &handle_frame_decrypt;
iwp_call_async_frame_decrypt(iwp, frame);
alloc_frame(inboundFrames, buf, sz);
}
else
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
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)
== -1)
llarp::Warn("sendto failed");
self->frames--;
}
template < typename Queue >
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
if(sz > 1500)
return nullptr;
iwp_async_frame *frame = new iwp_async_frame();
iwp_async_frame *frame = new iwp_async_frame;
if(buf)
memcpy(frame->buf, buf, sz);
frame->iwp = iwp;
frame->sz = sz;
frame->user = this;
frame->sessionkey = sessionkey;
frames++;
/// TODO: this could be rather slow
frame->created = now;
q.Put(frame);
return frame;
}
@ -1061,14 +1108,35 @@ namespace iwp
encrypt_frame_async_send(const void *buf, size_t sz)
{
// 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);
auto padding = rand() % MAX_PAD;
if(padding)
crypto->randbytes(frame->buf + 64 + 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
@ -1203,6 +1271,11 @@ namespace iwp
{
frame.alive();
state = st;
if(state == eLIMSent || state == eSessionStartSent)
{
PumpCodelInbound();
PumpCodelOutbound();
}
}
};
@ -1216,13 +1289,14 @@ namespace iwp
llarp_crypto *crypto;
llarp_ev_loop *netloop;
llarp_async_iwp *iwp;
llarp_threadpool *worker;
llarp_link *parent = nullptr;
llarp_udp_io udp;
llarp::Addr addr;
char keyfile[255];
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 >
LinkMap_t;
@ -1243,6 +1317,7 @@ namespace iwp
router = r;
crypto = c;
logic = l;
worker = w;
iwp = llarp_async_iwp_new(crypto, logic, w);
}
@ -1277,7 +1352,7 @@ namespace iwp
std::set< llarp::Addr > remove;
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))
remove.insert(itr.first);
}
@ -1300,7 +1375,7 @@ namespace iwp
auto inner_itr = serv->m_sessions.find(itr->second);
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);
}
}
@ -1350,28 +1425,28 @@ namespace iwp
if(itr == m_sessions.end())
return nullptr;
else
return static_cast< session * >(itr->second.impl);
return static_cast< session * >(itr->second->impl);
}
void
put_session(const llarp::Addr &src, session *impl)
{
llarp_link_session s = {};
s.impl = impl;
s.sendto = &session::sendto;
s.timeout = &session::is_timedout;
s.close = &session::close;
s.get_remote_router = &session::get_remote_router;
s.established = &session::set_established;
s.get_parent = &session::get_parent;
llarp_link_session *s = new llarp_link_session;
s->impl = impl;
s->sendto = &session::sendto;
s->timeout = &session::is_timedout;
s->close = &session::close;
s->get_remote_router = &session::get_remote_router;
s->established = &session::set_established;
s->get_parent = &session::get_parent;
{
lock_t lock(m_sessions_Mutex);
m_sessions[src] = s;
impl->parent = &m_sessions[src];
m_sessions.emplace(src, s);
impl->parent = m_sessions[src];
impl->frame.router = router;
impl->frame.parent = impl->parent;
impl->our_router = &router->rc;
}
impl->frame.router = router;
impl->frame.parent = impl->parent;
impl->our_router = &router->rc;
}
void
@ -1381,8 +1456,9 @@ namespace iwp
auto itr = m_sessions.begin();
while(itr != m_sessions.end())
{
session *s = static_cast< session * >(itr->second.impl);
session *s = static_cast< session * >(itr->second->impl);
delete s;
delete itr->second;
itr = m_sessions.erase(itr);
}
}
@ -1395,17 +1471,11 @@ namespace iwp
{
llarp::Debug("removing session ", addr);
UnmapAddr(addr);
session *s = static_cast< session * >(itr->second.impl);
session *s = static_cast< session * >(itr->second->impl);
s->done();
m_sessions.erase(addr);
if(s->frames)
{
llarp::Warn("session has ", s->frames,
" left but is idle, not deallocating session so we "
"leak but don't die");
}
else
delete s;
delete itr->second;
m_sessions.erase(itr);
delete s;
}
}
@ -1556,7 +1626,6 @@ namespace iwp
{
llarp::Error("intro verify failed from ", self->addr, " via ",
self->serv->addr);
delete self;
return;
}
self->intro_ack();
@ -1575,11 +1644,20 @@ namespace iwp
void
session::done()
{
auto logic = serv->logic;
if(establish_job_id)
{
llarp_logic_remove_call(logic, establish_job_id);
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
@ -1624,7 +1702,8 @@ namespace iwp
frame_header hdr(tmp);
hdr.flags() = self->frame.txflags;
// 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);
}
@ -1663,7 +1742,6 @@ namespace iwp
if(msg->completed())
{
llarp::Debug("message transmitted msgid=", msgid);
session *impl = static_cast< session * >(parent->impl);
tx.erase(msgid);
delete msg;
}
@ -1699,6 +1777,97 @@ namespace iwp
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
session::handle_verify_session_start(iwp_async_session_start *s)
{
@ -1829,7 +1998,7 @@ namespace iwp
link->timeout_job_id = 0;
link->logic = logic;
// start cleanup timer
link->issue_cleanup_timer(2500);
link->issue_cleanup_timer(1000);
return true;
}
@ -1854,8 +2023,8 @@ namespace iwp
iter.link = l;
// TODO: race condition with cleanup timer
for(auto &item : link->m_sessions)
if(item.second.impl)
if(!iter.visit(&iter, &item.second))
if(item.second->impl)
if(!iter.visit(&iter, item.second))
return;
}
}
@ -1933,6 +2102,7 @@ namespace iwp
delete link;
return;
}
link->frame.alive();
link->serv->put_session(link->addr, link);
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)

@ -47,23 +47,23 @@ struct llarp_nodedb
return entries.find(pk) != entries.end();
}
/*
bool
Has(const byte_t *pk)
{
llarp::PubKey test(pk);
auto itr = this->entries.begin();
while(itr != this->entries.end())
/*
bool
Has(const byte_t *pk)
{
llarp::Info("Has byte_t [", test.size(), "] vs [", itr->first.size(), "]");
if (memcmp(test.data(), itr->first.data(), 32) == 0) {
llarp::Info("Match");
llarp::PubKey test(pk);
auto itr = this->entries.begin();
while(itr != this->entries.end())
{
llarp::Info("Has byte_t [", test.size(), "] vs [", itr->first.size(),
"]"); if (memcmp(test.data(), itr->first.data(), 32) == 0) {
llarp::Info("Match");
}
itr++;
}
itr++;
return entries.find(pk) != entries.end();
}
return entries.find(pk) != entries.end();
}
*/
*/
bool
pubKeyExists(llarp_rc *rc)
@ -185,7 +185,7 @@ struct llarp_nodedb
auto itr = i.begin();
while(itr != itr.end())
{
if (fs::is_regular_file(itr->symlink_status()) && loadfile(*itr))
if(fs::is_regular_file(itr->symlink_status()) && loadfile(*itr))
sz++;
++itr;
@ -198,12 +198,13 @@ struct llarp_nodedb
{
#if __APPLE__ && __MACH__
// skip .DS_Store files
if (strstr(fpath.c_str(), ".DS_Store") != 0) {
if(strstr(fpath.c_str(), ".DS_Store") != 0)
{
return false;
}
#endif
llarp_rc *rc = llarp_rc_read(fpath.c_str());
if (!rc)
if(!rc)
{
llarp::Error("Signature read failed", fpath);
return false;
@ -218,8 +219,10 @@ struct llarp_nodedb
return true;
}
bool iterate(struct llarp_nodedb_iter i) {
i.index = 0;
bool
iterate(struct llarp_nodedb_iter i)
{
i.index = 0;
auto itr = entries.begin();
while(itr != entries.end())
{
@ -372,12 +375,14 @@ llarp_nodedb_load_dir(struct llarp_nodedb *n, const char *dir)
}
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);
}
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);
return n->entries.size();
}
@ -401,7 +406,7 @@ llarp_nodedb_async_load_rc(struct llarp_async_load_rc *job)
struct llarp_rc *
llarp_nodedb_get_rc(struct llarp_nodedb *n, const byte_t *pk)
{
//llarp::Info("llarp_nodedb_get_rc [", pk, "]");
// llarp::Info("llarp_nodedb_get_rc [", pk, "]");
if(n->Has(pk))
return n->getRC(pk);
else

@ -2,312 +2,403 @@
#include <llarp/encrypted_frame.hpp>
#include <llarp/path.hpp>
#include "buffer.hpp"
#include "pathbuilder.hpp"
#include "router.hpp"
namespace llarp
{
PathContext::PathContext(llarp_router* router)
: m_Router(router), m_AllowTransit(false)
namespace path
{
}
PathContext::PathContext(llarp_router* router)
: m_Router(router), m_AllowTransit(false)
{
}
PathContext::~PathContext()
{
}
PathContext::~PathContext()
{
}
void
PathContext::AllowTransit()
{
m_AllowTransit = true;
}
void
PathContext::AllowTransit()
{
m_AllowTransit = true;
}
bool
PathContext::AllowingTransit() const
{
return m_AllowTransit;
}
bool
PathContext::AllowingTransit() const
{
return m_AllowTransit;
}
llarp_threadpool*
PathContext::Worker()
{
return m_Router->tp;
}
llarp_threadpool*
PathContext::Worker()
{
return m_Router->tp;
}
llarp_crypto*
PathContext::Crypto()
{
return &m_Router->crypto;
}
llarp_crypto*
PathContext::Crypto()
{
return &m_Router->crypto;
}
llarp_logic*
PathContext::Logic()
{
return m_Router->logic;
}
llarp_logic*
PathContext::Logic()
{
return m_Router->logic;
}
byte_t*
PathContext::EncryptionSecretKey()
{
return m_Router->encryption;
}
byte_t*
PathContext::EncryptionSecretKey()
{
return m_Router->encryption;
}
bool
PathContext::HopIsUs(const PubKey& k) const
{
return memcmp(k, m_Router->pubkey(), PUBKEYSIZE) == 0;
}
bool
PathContext::HopIsUs(const PubKey& k) const
{
return memcmp(k, m_Router->pubkey(), PUBKEYSIZE) == 0;
}
bool
PathContext::ForwardLRCM(const RouterID& nextHop,
std::deque< EncryptedFrame >& frames)
{
llarp::Info("fowarding LRCM to ", nextHop);
LR_CommitMessage* msg = new LR_CommitMessage;
while(frames.size())
{
msg->frames.push_back(frames.front());
frames.pop_front();
}
return m_Router->SendToOrQueue(nextHop, msg);
}
template < typename Map_t, typename Key_t, typename CheckValue_t >
IHopHandler*
MapGet(Map_t& map, const Key_t& k, CheckValue_t check)
{
std::unique_lock< std::mutex > lock(map.first);
auto range = map.second.equal_range(k);
for(auto i = range.first; i != range.second; ++i)
bool
PathContext::ForwardLRCM(const RouterID& nextHop,
std::deque< EncryptedFrame >& frames)
{
llarp::Info("fowarding LRCM to ", nextHop);
LR_CommitMessage* msg = new LR_CommitMessage;
while(frames.size())
{
msg->frames.push_back(frames.front());
frames.pop_front();
}
return m_Router->SendToOrQueue(nextHop, msg);
}
template < typename Map_t, typename Key_t, typename CheckValue_t,
typename GetFunc_t >
IHopHandler*
MapGet(Map_t& map, const Key_t& k, CheckValue_t check, GetFunc_t get)
{
if(check(i->second))
return i->second;
std::unique_lock< std::mutex > lock(map.first);
auto range = map.second.equal_range(k);
for(auto i = range.first; i != range.second; ++i)
{
if(check(i->second))
return get(i->second);
}
return nullptr;
}
return nullptr;
}
template < typename Map_t, typename Key_t, typename CheckValue_t >
bool
MapHas(Map_t& map, const Key_t& k, CheckValue_t check)
{
std::unique_lock< std::mutex > lock(map.first);
auto range = map.second.equal_range(k);
for(auto i = range.first; i != range.second; ++i)
template < typename Map_t, typename Key_t, typename CheckValue_t >
bool
MapHas(Map_t& map, const Key_t& k, CheckValue_t check)
{
if(check(i->second))
return true;
std::unique_lock< std::mutex > lock(map.first);
auto range = map.second.equal_range(k);
for(auto i = range.first; i != range.second; ++i)
{
if(check(i->second))
return true;
}
return false;
}
return false;
}
template < typename Map_t, typename Key_t, typename Value_t >
void
MapPut(Map_t& map, const Key_t& k, const Value_t& v)
{
std::unique_lock< std::mutex > lock(map.first);
map.second.emplace(k, v);
}
template < typename Map_t, typename Key_t, typename Value_t >
void
MapPut(Map_t& map, const Key_t& k, const Value_t& v)
{
std::unique_lock< std::mutex > lock(map.first);
map.second.emplace(k, v);
}
template < typename Map_t, typename Visit_t >
void
MapIter(Map_t& map, Visit_t v)
{
std::unique_lock< std::mutex > lock(map.first);
for(const auto& item : map.second)
v(item);
}
template < typename Map_t, typename Key_t, typename Check_t >
void
MapDel(Map_t& map, const Key_t& k, Check_t check)
{
std::unique_lock< std::mutex > lock(map.first);
auto range = map.second.equal_range(k);
for(auto i = range.first; i != range.second;)
template < typename Map_t, typename Visit_t >
void
MapIter(Map_t& map, Visit_t v)
{
if(check(i->second))
i = map.second.erase(i);
else
++i;
std::unique_lock< std::mutex > lock(map.first);
for(const auto& item : map.second)
v(item);
}
}
void
PathContext::AddOwnPath(Path* path)
{
MapPut(m_OurPaths, path->TXID(), path);
MapPut(m_OurPaths, path->RXID(), path);
}
template < typename Map_t, typename Key_t, typename Check_t >
void
MapDel(Map_t& map, const Key_t& k, Check_t check)
{
std::unique_lock< std::mutex > lock(map.first);
auto range = map.second.equal_range(k);
for(auto i = range.first; i != range.second;)
{
if(check(i->second))
i = map.second.erase(i);
else
++i;
}
}
bool
PathContext::HasTransitHop(const TransitHopInfo& info)
{
return MapHas(m_TransitPaths, info.txID, [info](TransitHop* hop) -> bool {
return info == hop->info;
});
}
void
PathContext::AddOwnPath(PathSet* set, Path* path)
{
set->AddPath(path);
MapPut(m_OurPaths, path->TXID(), set);
MapPut(m_OurPaths, path->RXID(), set);
}
IHopHandler*
PathContext::GetByUpstream(const RouterID& remote, const PathID_t& id)
{
auto own = MapGet(m_OurPaths, id, [remote](const Path* p) -> bool {
return p->Upstream() == remote;
});
if(own)
return own;
return MapGet(m_TransitPaths, id, [remote](const TransitHop* hop) -> bool {
return hop->info.upstream == remote;
});
}
IHopHandler*
PathContext::GetByDownstream(const RouterID& remote, const PathID_t& id)
{
return MapGet(m_TransitPaths, id, [remote](const TransitHop* hop) -> bool {
return hop->info.downstream == remote;
});
}
bool
PathContext::HasTransitHop(const TransitHopInfo& info)
{
return MapHas(m_TransitPaths, info.txID, [info](TransitHop* hop) -> bool {
return info == hop->info;
});
}
const byte_t*
PathContext::OurRouterID() const
{
return m_Router->pubkey();
}
IHopHandler*
PathContext::GetByUpstream(const RouterID& remote, const PathID_t& id)
{
auto own = MapGet(m_OurPaths, id,
[](const PathSet* s) -> bool {
// TODO: is this right?
return true;
},
[remote, id](PathSet* p) -> IHopHandler* {
return p->GetByUpstream(remote, id);
});
if(own)
return own;
return MapGet(m_TransitPaths, id,
[remote](const TransitHop* hop) -> bool {
return hop->info.upstream == remote;
},
[](TransitHop* h) -> IHopHandler* { return h; });
}
llarp_router*
PathContext::Router()
{
return m_Router;
}
IHopHandler*
PathContext::GetByDownstream(const RouterID& remote, const PathID_t& id)
{
return MapGet(m_TransitPaths, id,
[remote](const TransitHop* hop) -> bool {
return hop->info.downstream == remote;
},
[](TransitHop* h) -> IHopHandler* { return h; });
}
void
PathContext::PutTransitHop(TransitHop* hop)
{
MapPut(m_TransitPaths, hop->info.txID, hop);
MapPut(m_TransitPaths, hop->info.rxID, hop);
}
const byte_t*
PathContext::OurRouterID() const
{
return m_Router->pubkey();
}
void
PathContext::ExpirePaths()
{
std::unique_lock< std::mutex > lock(m_TransitPaths.first);
auto now = llarp_time_now_ms();
auto& map = m_TransitPaths.second;
auto itr = map.begin();
std::set< TransitHop* > removePaths;
while(itr != map.end())
{
if(itr->second->Expired(now))
llarp_router*
PathContext::Router()
{
return m_Router;
}
void
PathContext::PutTransitHop(TransitHop* hop)
{
MapPut(m_TransitPaths, hop->info.txID, hop);
MapPut(m_TransitPaths, hop->info.rxID, hop);
}
void
PathContext::ExpirePaths()
{
std::unique_lock< std::mutex > lock(m_TransitPaths.first);
auto now = llarp_time_now_ms();
auto& map = m_TransitPaths.second;
auto itr = map.begin();
std::set< TransitHop* > removePaths;
while(itr != map.end())
{
if(itr->second->Expired(now))
{
TransitHop* path = itr->second;
llarp::Info("transit path expired ", path);
removePaths.insert(path);
}
++itr;
}
for(auto& p : removePaths)
{
map.erase(p->info.txID);
map.erase(p->info.rxID);
delete p;
}
for(auto& builder : m_PathBuilders)
{
TransitHop* path = itr->second;
llarp::Info("transit path expired ", path);
removePaths.insert(path);
builder->ExpirePaths(now);
}
++itr;
}
for(auto& p : removePaths)
void
PathContext::BuildPaths()
{
map.erase(p->info.txID);
map.erase(p->info.rxID);
delete p;
for(auto& builder : m_PathBuilders)
{
if(builder->ShouldBuildMore())
{
builder->BuildOne();
}
}
}
}
Path::Path(llarp_path_hops* h) : hops(h->numHops)
{
for(size_t idx = 0; idx < h->numHops; ++idx)
void
PathContext::AddPathBuilder(llarp_pathbuilder_context* ctx)
{
llarp_rc_copy(&hops[idx].router, &h->hops[idx].router);
hops[idx].txID.Randomize();
hops[idx].rxID.Randomize();
m_PathBuilders.push_back(ctx);
}
for(size_t idx = (h->numHops - 1); idx > 0; --idx)
PathHopConfig::PathHopConfig()
{
hops[idx].txID = hops[idx - 1].rxID;
llarp_rc_clear(&router);
}
}
const PathID_t&
Path::TXID() const
{
return hops[0].txID;
}
PathHopConfig::~PathHopConfig()
{
llarp_rc_free(&router);
}
const PathID_t&
Path::RXID() const
{
return hops[0].rxID;
}
Path::Path(llarp_path_hops* h) : hops(h->numHops)
{
for(size_t idx = 0; idx < h->numHops; ++idx)
{
llarp_rc_copy(&hops[idx].router, &h->hops[idx].router);
hops[idx].txID.Randomize();
hops[idx].rxID.Randomize();
}
for(size_t idx = (h->numHops - 1); idx > 0; --idx)
{
hops[idx].txID = hops[idx - 1].rxID;
}
}
RouterID
Path::Upstream() const
{
return hops[0].router.pubkey;
}
void
Path::SetBuildResultHook(BuildResultHookFunc func)
{
m_BuiltHook = func;
}
bool
Path::HandleUpstream(llarp_buffer_t buf, const TunnelNonce& Y,
llarp_router* r)
{
for(const auto& hop : hops)
const PathID_t&
Path::TXID() const
{
r->crypto.xchacha20(buf, hop.shared, Y);
return hops[0].txID;
}
RelayUpstreamMessage* msg = new RelayUpstreamMessage;
msg->X = buf;
msg->Y = Y;
msg->pathid = TXID();
return r->SendToOrQueue(Upstream(), msg);
}
bool
Path::Expired(llarp_time_t now) const
{
return now - buildStarted > hops[0].lifetime;
}
const PathID_t&
Path::RXID() const
{
return hops[0].rxID;
}
bool
Path::HandleDownstream(llarp_buffer_t buf, const TunnelNonce& Y,
RouterID
Path::Upstream() const
{
return hops[0].router.pubkey;
}
bool
Path::HandleUpstream(llarp_buffer_t buf, const TunnelNonce& Y,
llarp_router* r)
{
for(const auto& hop : hops)
{
r->crypto.xchacha20(buf, hop.shared, Y);
for(const auto& hop : hops)
{
r->crypto.xchacha20(buf, hop.shared, Y);
}
RelayUpstreamMessage* msg = new RelayUpstreamMessage;
msg->X = buf;
msg->Y = Y;
msg->pathid = TXID();
return r->SendToOrQueue(Upstream(), msg);
}
return HandleRoutingMessage(buf, r);
}
bool
Path::HandleHiddenServiceData(llarp_buffer_t buf)
{
// TODO: implement me
return false;
}
bool
Path::Expired(llarp_time_t now) const
{
if(status == ePathEstablished)
return now - buildStarted > hops[0].lifetime;
else if(status == ePathBuilding)
return now - buildStarted > PATH_BUILD_TIMEOUT;
else
return true;
}
bool
Path::HandleRoutingMessage(llarp_buffer_t buf, llarp_router* r)
{
if(!m_InboundMessageParser.ParseMessageBuffer(buf, this))
bool
Path::HandleDownstream(llarp_buffer_t buf, const TunnelNonce& Y,
llarp_router* r)
{
llarp::Warn("Failed to parse inbound routing message");
for(const auto& hop : hops)
{
r->crypto.xchacha20(buf, hop.shared, Y);
}
return HandleRoutingMessage(buf, r);
}
bool
Path::HandleHiddenServiceData(llarp_buffer_t buf)
{
// TODO: implement me
return false;
}
return true;
}
bool
Path::SendRoutingMessage(const llarp::routing::IMessage* msg, llarp_router* r)
{
byte_t tmp[MAX_LINK_MSG_SIZE / 2];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
if(!msg->BEncode(&buf))
bool
Path::HandleRoutingMessage(llarp_buffer_t buf, llarp_router* r)
{
if(!m_InboundMessageParser.ParseMessageBuffer(buf, this))
{
llarp::Warn("Failed to parse inbound routing message");
return false;
}
return true;
}
bool
Path::SendRoutingMessage(const llarp::routing::IMessage* msg,
llarp_router* r)
{
byte_t tmp[MAX_LINK_MSG_SIZE / 2];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
if(!msg->BEncode(&buf))
return false;
// rewind
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
// make nonce
TunnelNonce N;
N.Randomize();
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;
// rewind
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
// make nonce
TunnelNonce N;
N.Randomize();
return HandleUpstream(buf, N, r);
}
}
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

@ -9,7 +9,10 @@ namespace llarp
template < typename User >
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 >*);
User* user = nullptr;
Handler result = nullptr;
@ -105,8 +108,8 @@ namespace llarp
/// Generate all keys asynchronously and call hadler when done
void
AsyncGenerateKeys(Path* p, llarp_logic* l, llarp_threadpool* pool, User* u,
Handler func)
AsyncGenerateKeys(Path_t* p, llarp_logic* l, llarp_threadpool* pool,
User* u, Handler func)
{
path = p;
logic = l;
@ -124,16 +127,6 @@ namespace llarp
}
};
PathHopConfig::PathHopConfig()
{
llarp_rc_clear(&router);
}
PathHopConfig::~PathHopConfig()
{
llarp_rc_free(&router);
}
void
pathbuilder_generated_keys(
AsyncPathKeyExchangeContext< llarp_pathbuild_job >* ctx)
@ -146,8 +139,8 @@ namespace llarp
llarp::Error("failed to send LRCM");
return;
}
ctx->path->status = ePathBuilding;
router->paths.AddOwnPath(ctx->path);
ctx->path->status = llarp::path::ePathBuilding;
router->paths.AddOwnPath(ctx->pathset, ctx->path);
ctx->user->pathBuildStarted(ctx->user);
}
@ -171,16 +164,33 @@ namespace llarp
AsyncPathKeyExchangeContext< llarp_pathbuild_job >* ctx =
new AsyncPathKeyExchangeContext< llarp_pathbuild_job >(
&job->router->crypto);
ctx->AsyncGenerateKeys(new Path(&job->hops), job->router->logic,
job->router->tp, job, &pathbuilder_generated_keys);
ctx->pathset = job->context;
auto path = new llarp::path::Path(&job->hops);
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
llarp_pathbuilder_context::llarp_pathbuilder_context(
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" {
@ -200,7 +210,7 @@ llarp_pathbuilder_context_free(struct llarp_pathbuilder_context* ctx)
void
llarp_pathbuilder_build_path(struct llarp_pathbuild_job* job)
{
if (!job->context)
if(!job->context)
{
llarp::Error("failed to build path because no context is set in job");
return;
@ -211,4 +221,4 @@ llarp_pathbuilder_build_path(struct llarp_pathbuild_job* job)
llarp_logic_queue_job(job->router->logic,
{job, &llarp::pathbuilder_start_build});
}
} // end extern c
} // end extern c

@ -2,13 +2,16 @@
#define LLARP_PATHFINDER_HPP_
#include <llarp/pathbuilder.h>
struct llarp_pathbuilder_context
struct llarp_pathbuilder_context : public llarp::path::PathSet
{
struct llarp_router* router;
struct llarp_dht_context* dht;
/// copy cstr
/// construct
llarp_pathbuilder_context(llarp_router* p_router,
struct llarp_dht_context* p_dht);
void
BuildOne();
};
#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
{
typedef llarp::path::PathContext Context;
typedef llarp::path::TransitHop Hop;
typedef AsyncFrameDecrypter< LRCMFrameDecrypt > Decrypter;
Decrypter* decrypter;
std::deque< EncryptedFrame > frames;
PathContext* context;
Context* context;
// decrypted record
LR_CommitRecord record;
// the actual hop
TransitHop* hop;
Hop* hop;
LRCMFrameDecrypt(PathContext* ctx, Decrypter* dec,
LRCMFrameDecrypt(Context* ctx, Decrypter* dec,
const LR_CommitMessage* commit)
: decrypter(dec), context(ctx), hop(new TransitHop)
: decrypter(dec), context(ctx), hop(new Hop)
{
for(const auto& f : commit->frames)
frames.push_back(f);
@ -276,7 +278,7 @@ namespace llarp
};
bool
LR_CommitMessage::AsyncDecrypt(PathContext* context) const
LR_CommitMessage::AsyncDecrypt(llarp::path::PathContext* context) const
{
LRCMFrameDecrypt::Decrypter* decrypter = new LRCMFrameDecrypt::Decrypter(
context->Crypto(), context->EncryptionSecretKey(),

@ -356,6 +356,7 @@ llarp_router::HandleExploritoryPathBuildStarted(llarp_pathbuild_job *job)
delete job;
}
// TODO: do we still need this?
void
llarp_router::BuildExploritoryPath()
{
@ -379,7 +380,7 @@ llarp_router::Tick()
auto N = llarp_nodedb_num_loaded(nodedb);
if(N > 5)
{
BuildExploritoryPath();
paths.BuildPaths();
}
else
{
@ -595,16 +596,14 @@ llarp_router::Run()
// set public encryption key
llarp_rc_set_pubenckey(&rc, llarp::seckey_topublic(encryption));
char ftmp[68] = {0};
const char *hexKey = llarp::HexEncode< llarp::PubKey,
decltype(ftmp) >(llarp::seckey_topublic(encryption),
ftmp);
char ftmp[68] = {0};
const char *hexKey = llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(
llarp::seckey_topublic(encryption), ftmp);
llarp::Info("Your Encryption pubkey ", hexKey);
// set public signing key
llarp_rc_set_pubsigkey(&rc, llarp::seckey_topublic(identity));
hexKey = llarp::HexEncode< llarp::PubKey,
decltype(ftmp) >(llarp::seckey_topublic(identity),
ftmp);
hexKey = llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(
llarp::seckey_topublic(identity), ftmp);
llarp::Info("Your Identity pubkey ", hexKey);
llarp_rc_sign(&crypto, identity, &rc);
@ -641,14 +640,16 @@ llarp_router::Run()
// immediate connect all for service node
uint64_t delay = rand() % 100;
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
{
// delayed connect all for clients
uint64_t delay = ((rand() % 10) * 500) + 1000;
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();
@ -850,7 +851,7 @@ llarp_rc_read(const char *fpath)
return 0;
f.read((char *)buf.base, sz);
//printf("contents[%s]\n", tmpc);
// printf("contents[%s]\n", tmpc);
llarp_rc *rc = new llarp_rc;
llarp::Zero(rc, sizeof(llarp_rc));
if(!llarp_rc_bdecode(rc, &buf))
@ -977,12 +978,12 @@ llarp_findOrCreateIdentity(llarp_crypto *crypto, const char *fpath,
return false;
}
} // end extern C
} // end extern C
// C++ ...
bool
llarp_findOrCreateEncryption(llarp_crypto *crypto, const char *fpath,
llarp::SecretKey *encryption)
llarp::SecretKey *encryption)
{
llarp::Debug("find or create ", fpath);
fs::path path(fpath);

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

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

@ -4,85 +4,87 @@
namespace llarp
{
bool
TransitHop::Expired(llarp_time_t now) const
namespace path
{
return now - started > lifetime;
}
TransitHopInfo::TransitHopInfo(const TransitHopInfo& other)
: txID(other.txID)
, rxID(other.rxID)
, upstream(other.upstream)
, downstream(other.downstream)
{
}
bool
TransitHop::Expired(llarp_time_t now) const
{
return now - started > lifetime;
}
TransitHopInfo::TransitHopInfo(const RouterID& down,
const LR_CommitRecord& record)
: txID(record.txid)
, rxID(record.rxid)
, upstream(record.nextHop)
, downstream(down)
{
}
TransitHopInfo::TransitHopInfo(const TransitHopInfo& other)
: txID(other.txID)
, rxID(other.rxID)
, upstream(other.upstream)
, downstream(other.downstream)
{
}
TransitHop::TransitHop(const TransitHop& other)
: info(other.info)
, pathKey(other.pathKey)
, started(other.started)
, lifetime(other.lifetime)
, version(other.version)
{
}
TransitHopInfo::TransitHopInfo(const RouterID& down,
const LR_CommitRecord& record)
: txID(record.txid)
, rxID(record.rxid)
, upstream(record.nextHop)
, downstream(down)
{
}
bool
TransitHop::SendRoutingMessage(const llarp::routing::IMessage* msg,
llarp_router* r)
{
byte_t tmp[MAX_LINK_MSG_SIZE / 2];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
if(!msg->BEncode(&buf))
TransitHop::TransitHop(const TransitHop& other)
: info(other.info)
, pathKey(other.pathKey)
, started(other.started)
, lifetime(other.lifetime)
, version(other.version)
{
llarp::Error("failed to encode routing message");
return false;
}
TunnelNonce N;
N.Randomize();
// rewind
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
return HandleDownstream(buf, N, r);
}
bool
TransitHop::HandleDownstream(llarp_buffer_t buf, const TunnelNonce& Y,
llarp_router* r)
{
RelayDownstreamMessage* msg = new RelayDownstreamMessage;
msg->pathid = info.txID;
msg->Y = Y;
bool
TransitHop::SendRoutingMessage(const llarp::routing::IMessage* msg,
llarp_router* r)
{
byte_t tmp[MAX_LINK_MSG_SIZE / 2];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
if(!msg->BEncode(&buf))
{
llarp::Error("failed to encode routing message");
return false;
}
TunnelNonce N;
N.Randomize();
// rewind
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
return HandleDownstream(buf, N, r);
}
r->crypto.xchacha20(buf, pathKey, Y);
msg->X = buf;
llarp::Info("relay ", msg->X.size(), " bytes downstream from ",
info.upstream, " to ", info.downstream);
return r->SendToOrQueue(info.downstream, msg);
}
bool
TransitHop::HandleDownstream(llarp_buffer_t buf, const TunnelNonce& Y,
llarp_router* r)
{
RelayDownstreamMessage* msg = new RelayDownstreamMessage;
msg->pathid = info.txID;
msg->Y = Y;
bool
TransitHop::HandleUpstream(llarp_buffer_t buf, const TunnelNonce& Y,
llarp_router* r)
{
RelayUpstreamMessage* msg = new RelayUpstreamMessage;
msg->pathid = info.rxID;
msg->Y = Y;
r->crypto.xchacha20(buf, pathKey, Y);
msg->X = buf;
llarp::Info("relay ", msg->X.size(), " bytes downstream from ",
info.upstream, " to ", info.downstream);
return r->SendToOrQueue(info.downstream, msg);
}
r->crypto.xchacha20(buf, pathKey, Y);
msg->X = buf;
llarp::Info("relay ", msg->X.size(), " bytes upstream from ",
info.downstream, " to ", info.upstream);
return r->SendToOrQueue(info.upstream, msg);
}
bool
TransitHop::HandleUpstream(llarp_buffer_t buf, const TunnelNonce& Y,
llarp_router* r)
{
RelayUpstreamMessage* msg = new RelayUpstreamMessage;
msg->pathid = info.rxID;
msg->Y = Y;
r->crypto.xchacha20(buf, pathKey, Y);
msg->X = buf;
llarp::Info("relay ", msg->X.size(), " bytes upstream from ",
info.downstream, " to ", info.upstream);
return r->SendToOrQueue(info.upstream, msg);
}
} // namespace path
} // namespace llarp

Loading…
Cancel
Save