mirror of https://github.com/oxen-io/lokinet
initial path building stuff (broken)
This commit is contained in:
parent
bdc043d2a2
commit
08c0318e82
|
@ -6,12 +6,14 @@
|
|||
"path": [
|
||||
"${workspaceFolder}/llarp",
|
||||
"${workspaceFolder}/daemon",
|
||||
"${workspaceFolder}/include"
|
||||
"${workspaceFolder}/include",
|
||||
"${workspaceFolder}/vendor/cppbackport-master/lib"
|
||||
],
|
||||
"limitSymbolsToIncludedHeaders": true
|
||||
},
|
||||
"includePath": [
|
||||
"${workspaceFolder}/include"
|
||||
"${workspaceFolder}/include",
|
||||
"${workspaceFolder}/vendor/cppbackport-master/lib"
|
||||
],
|
||||
"defines": [],
|
||||
"compilerPath": "/usr/bin/clang",
|
||||
|
|
|
@ -1,3 +1,59 @@
|
|||
{
|
||||
"editor.formatOnSave": true
|
||||
"editor.formatOnSave": true,
|
||||
"files.associations": {
|
||||
"array": "cpp",
|
||||
"limits": "cpp",
|
||||
"cctype": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"atomic": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"bitset": "cpp",
|
||||
"chrono": "cpp",
|
||||
"codecvt": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"deque": "cpp",
|
||||
"list": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"exception": "cpp",
|
||||
"filesystem": "cpp",
|
||||
"string_view": "cpp",
|
||||
"fstream": "cpp",
|
||||
"functional": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"memory": "cpp",
|
||||
"mutex": "cpp",
|
||||
"optional": "cpp",
|
||||
"ostream": "cpp",
|
||||
"ratio": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"system_error": "cpp",
|
||||
"thread": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"tuple": "cpp",
|
||||
"typeindex": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"utility": "cpp",
|
||||
"__config": "cpp",
|
||||
"__nullptr": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"io": "cpp"
|
||||
}
|
||||
}
|
|
@ -7,7 +7,10 @@
|
|||
"label": "build",
|
||||
"type": "shell",
|
||||
"command": "make",
|
||||
"group": "build"
|
||||
"group": "build",
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -59,8 +59,8 @@ if(SHADOW)
|
|||
include_directories(${SHADOW_ROOT}/include)
|
||||
endif()
|
||||
|
||||
add_cflags("-Wall ${OPTIMIZE_FLAGS}")
|
||||
add_cxxflags("-Wall ${OPTIMIZE_FLAGS}")
|
||||
add_cflags("-Wall -Wno-deprecated-declarations ${OPTIMIZE_FLAGS}")
|
||||
add_cxxflags("-Wall -Wno-deprecated-declarations ${OPTIMIZE_FLAGS}")
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]")
|
||||
add_cflags("${DEBUG_FLAGS}")
|
||||
|
@ -123,12 +123,13 @@ set(LIB_SRC
|
|||
llarp/net.cpp
|
||||
llarp/nodedb.cpp
|
||||
llarp/path.cpp
|
||||
llarp/pathbuilder.cpp
|
||||
llarp/proofofwork.cpp
|
||||
llarp/relay_ack.cpp
|
||||
llarp/relay_commit.cpp
|
||||
llarp/relay_up_down.cpp
|
||||
llarp/router_contact.cpp
|
||||
llarp/router.cpp
|
||||
llarp/router_identity.c
|
||||
llarp/threadpool.cpp
|
||||
llarp/testnet.c
|
||||
llarp/time.cpp
|
||||
|
|
|
@ -145,7 +145,7 @@ main(int argc, char *argv[])
|
|||
int c;
|
||||
char *rcfname;
|
||||
char defaultName[] = "other.signed";
|
||||
rcfname = defaultName;
|
||||
rcfname = defaultName;
|
||||
while(1)
|
||||
{
|
||||
static struct option long_options[] = {
|
||||
|
|
|
@ -142,6 +142,6 @@ namespace llarp
|
|||
uint64_t l[sz / 8];
|
||||
};
|
||||
};
|
||||
}
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
||||
|
|
|
@ -9,9 +9,6 @@ namespace llarp
|
|||
{
|
||||
struct LR_AckRecord
|
||||
{
|
||||
PubKey pubkey;
|
||||
TunnelNonce nonce;
|
||||
PathID_t rxPathID;
|
||||
uint64_t version = 0;
|
||||
|
||||
bool
|
||||
|
@ -23,9 +20,7 @@ namespace llarp
|
|||
|
||||
struct LR_AckMessage : public ILinkMessage
|
||||
{
|
||||
std::vector< EncryptedFrame > acks;
|
||||
EncryptedFrame lasthopFrame;
|
||||
PathID_t txPathID;
|
||||
std::vector< EncryptedFrame > replies;
|
||||
uint64_t version = 0;
|
||||
|
||||
LR_AckMessage(const RouterID& from);
|
||||
|
@ -41,6 +36,6 @@ namespace llarp
|
|||
bool
|
||||
HandleMessage(llarp_router* router) const;
|
||||
};
|
||||
}
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,18 +5,21 @@
|
|||
#include <llarp/encrypted_frame.hpp>
|
||||
#include <llarp/link_message.hpp>
|
||||
#include <llarp/path_types.hpp>
|
||||
#include <llarp/pow.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
// forward declare
|
||||
struct PathContext;
|
||||
|
||||
struct LR_CommitRecord
|
||||
{
|
||||
PubKey commkey;
|
||||
PubKey nextHop;
|
||||
RouterID nextHop;
|
||||
TunnelNonce tunnelNonce;
|
||||
PathID_t txid;
|
||||
SymmKey downstreamReplyKey;
|
||||
SymmNonce downstreamReplyNonce;
|
||||
PathID_t pathid;
|
||||
PoW *work = nullptr;
|
||||
uint64_t version;
|
||||
|
||||
bool
|
||||
|
@ -25,6 +28,8 @@ namespace llarp
|
|||
bool
|
||||
BEncode(llarp_buffer_t *buf) const;
|
||||
|
||||
~LR_CommitRecord();
|
||||
|
||||
private:
|
||||
static bool
|
||||
OnKey(dict_reader *r, llarp_buffer_t *buf);
|
||||
|
@ -32,9 +37,10 @@ namespace llarp
|
|||
|
||||
struct LR_AcceptRecord
|
||||
{
|
||||
uint64_t pathid;
|
||||
uint64_t version;
|
||||
std::vector< byte_t > padding;
|
||||
RouterID upstream;
|
||||
RouterID downstream;
|
||||
PathID_t pathid;
|
||||
uint64_t version = LLARP_PROTO_VERSION;
|
||||
|
||||
bool
|
||||
DecodeKey(llarp_buffer_t key, llarp_buffer_t *buf);
|
||||
|
@ -46,13 +52,12 @@ namespace llarp
|
|||
struct LR_CommitMessage : public ILinkMessage
|
||||
{
|
||||
std::vector< EncryptedFrame > frames;
|
||||
EncryptedFrame lasthopFrame;
|
||||
std::vector< EncryptedAck > acks;
|
||||
uint64_t version;
|
||||
|
||||
LR_CommitMessage() : ILinkMessage()
|
||||
{
|
||||
}
|
||||
|
||||
LR_CommitMessage(const RouterID &from) : ILinkMessage(from)
|
||||
{
|
||||
}
|
||||
|
@ -70,7 +75,10 @@ namespace llarp
|
|||
|
||||
bool
|
||||
HandleMessage(llarp_router *router) const;
|
||||
|
||||
bool
|
||||
AsyncDecrypt(PathContext *context) const;
|
||||
};
|
||||
}
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,119 +11,129 @@
|
|||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
struct llarp_nodedb;
|
||||
struct llarp_nodedb;
|
||||
|
||||
/// create an empty nodedb
|
||||
struct llarp_nodedb *
|
||||
llarp_nodedb_new(struct llarp_crypto *crypto);
|
||||
/// create an empty nodedb
|
||||
struct llarp_nodedb *
|
||||
llarp_nodedb_new(struct llarp_crypto *crypto);
|
||||
|
||||
/// free a nodedb and all loaded rc
|
||||
void
|
||||
llarp_nodedb_free(struct llarp_nodedb **n);
|
||||
/// free a nodedb and all loaded rc
|
||||
void
|
||||
llarp_nodedb_free(struct llarp_nodedb **n);
|
||||
|
||||
/// ensure a nodedb fs skiplist structure is at dir
|
||||
/// create if not there.
|
||||
bool
|
||||
llarp_nodedb_ensure_dir(const char *dir);
|
||||
/// ensure a nodedb fs skiplist structure is at dir
|
||||
/// create if not there.
|
||||
bool
|
||||
llarp_nodedb_ensure_dir(const char *dir);
|
||||
|
||||
/// load entire nodedb from fs skiplist at dir
|
||||
ssize_t
|
||||
llarp_nodedb_load_dir(struct llarp_nodedb *n, const char *dir);
|
||||
/// load entire nodedb from fs skiplist at dir
|
||||
ssize_t
|
||||
llarp_nodedb_load_dir(struct llarp_nodedb *n, const char *dir);
|
||||
|
||||
/// store entire nodedb to fs skiplist at dir
|
||||
ssize_t
|
||||
llarp_nodedb_store_dir(struct llarp_nodedb *n, const char *dir);
|
||||
/// store entire nodedb to fs skiplist at dir
|
||||
ssize_t
|
||||
llarp_nodedb_store_dir(struct llarp_nodedb *n, const char *dir);
|
||||
|
||||
struct llarp_nodedb_iter
|
||||
{
|
||||
void *user;
|
||||
struct llarp_rc *rc;
|
||||
bool (*visit)(struct llarp_nodedb_iter *);
|
||||
};
|
||||
struct llarp_nodedb_iter
|
||||
{
|
||||
void *user;
|
||||
struct llarp_rc *rc;
|
||||
bool (*visit)(struct llarp_nodedb_iter *);
|
||||
};
|
||||
|
||||
/// iterate over all loaded rc with an iterator
|
||||
void
|
||||
llarp_nodedb_iterate_all(struct llarp_nodedb *n, struct llarp_nodedb_iter i);
|
||||
/// iterate over all loaded rc with an iterator
|
||||
void
|
||||
llarp_nodedb_iterate_all(struct llarp_nodedb *n, struct llarp_nodedb_iter i);
|
||||
|
||||
/**
|
||||
put an rc into the node db
|
||||
overwrites with new contents if already present
|
||||
flushes the single entry to disk
|
||||
returns true on success and false on error
|
||||
*/
|
||||
bool
|
||||
llarp_nodedb_put_rc(struct llarp_nodedb *n, struct llarp_rc *rc);
|
||||
/// get a random rc that is loaded
|
||||
void
|
||||
llarp_nodedb_get_random_rc(struct llarp_nodedb *n, struct llarp_rc *result);
|
||||
|
||||
/// return a pointer to an already loaded RC or nullptr if it's not there
|
||||
struct llarp_rc *
|
||||
llarp_nodedb_get_rc(struct llarp_nodedb *n, const byte_t *pk);
|
||||
/// select a random rc at hop number N
|
||||
void
|
||||
llarp_nodedb_select_random_hop(struct llarp_nodedb *n,
|
||||
struct llarp_rc *result, size_t N);
|
||||
/**
|
||||
put an rc into the node db
|
||||
overwrites with new contents if already present
|
||||
flushes the single entry to disk
|
||||
returns true on success and false on error
|
||||
*/
|
||||
bool
|
||||
llarp_nodedb_put_rc(struct llarp_nodedb *n, struct llarp_rc *rc);
|
||||
|
||||
/// struct for async rc verification
|
||||
struct llarp_async_verify_rc;
|
||||
/// return a pointer to an already loaded RC or nullptr if it's not there
|
||||
struct llarp_rc *
|
||||
llarp_nodedb_get_rc(struct llarp_nodedb *n, const byte_t *pk);
|
||||
|
||||
typedef void (*llarp_async_verify_rc_hook_func)(struct llarp_async_verify_rc *);
|
||||
/// struct for async rc verification
|
||||
struct llarp_async_verify_rc;
|
||||
|
||||
/// verify rc request
|
||||
struct llarp_async_verify_rc
|
||||
{
|
||||
/// async_verify_context
|
||||
void *user;
|
||||
/// nodedb storage
|
||||
struct llarp_nodedb *nodedb;
|
||||
// llarp_logic for llarp_logic_queue_job
|
||||
struct llarp_logic *logic; // includes a llarp_threadpool
|
||||
// struct llarp_crypto *crypto; // probably don't need this because we have it
|
||||
// in the nodedb
|
||||
struct llarp_threadpool *cryptoworker;
|
||||
struct llarp_threadpool *diskworker;
|
||||
typedef void (*llarp_async_verify_rc_hook_func)(
|
||||
struct llarp_async_verify_rc *);
|
||||
|
||||
/// router contact (should this be a pointer?)
|
||||
struct llarp_rc rc;
|
||||
/// result
|
||||
bool valid;
|
||||
/// hook
|
||||
llarp_async_verify_rc_hook_func hook;
|
||||
};
|
||||
/// verify rc request
|
||||
struct llarp_async_verify_rc
|
||||
{
|
||||
/// async_verify_context
|
||||
void *user;
|
||||
/// nodedb storage
|
||||
struct llarp_nodedb *nodedb;
|
||||
// llarp_logic for llarp_logic_queue_job
|
||||
struct llarp_logic *logic; // includes a llarp_threadpool
|
||||
// struct llarp_crypto *crypto; // probably don't need this because we have
|
||||
// it in the nodedb
|
||||
struct llarp_threadpool *cryptoworker;
|
||||
struct llarp_threadpool *diskworker;
|
||||
|
||||
/**
|
||||
struct for async rc verification
|
||||
data is loaded in disk io threadpool
|
||||
crypto is done on the crypto worker threadpool
|
||||
result is called on the logic thread
|
||||
*/
|
||||
void
|
||||
llarp_nodedb_async_verify(struct llarp_async_verify_rc *job);
|
||||
/// router contact (should this be a pointer?)
|
||||
struct llarp_rc rc;
|
||||
/// result
|
||||
bool valid;
|
||||
/// hook
|
||||
llarp_async_verify_rc_hook_func hook;
|
||||
};
|
||||
|
||||
struct llarp_async_load_rc;
|
||||
/**
|
||||
struct for async rc verification
|
||||
data is loaded in disk io threadpool
|
||||
crypto is done on the crypto worker threadpool
|
||||
result is called on the logic thread
|
||||
*/
|
||||
void
|
||||
llarp_nodedb_async_verify(struct llarp_async_verify_rc *job);
|
||||
|
||||
typedef void (*llarp_async_load_rc_hook_func)(struct llarp_async_load_rc *);
|
||||
struct llarp_async_load_rc;
|
||||
|
||||
struct llarp_async_load_rc
|
||||
{
|
||||
/// async_verify_context
|
||||
void *user;
|
||||
/// nodedb storage
|
||||
struct llarp_nodedb *nodedb;
|
||||
/// llarp_logic for calling hook
|
||||
struct llarp_logic *logic;
|
||||
/// disk worker threadpool
|
||||
struct llarp_threadpool *diskworker;
|
||||
/// target pubkey
|
||||
byte_t pubkey[PUBKEYSIZE];
|
||||
/// router contact result
|
||||
struct llarp_rc rc;
|
||||
/// set to true if we loaded the rc
|
||||
bool loaded;
|
||||
/// hook function called in logic thread
|
||||
llarp_async_load_rc_hook_func hook;
|
||||
};
|
||||
typedef void (*llarp_async_load_rc_hook_func)(struct llarp_async_load_rc *);
|
||||
|
||||
/// asynchronously load an rc from disk
|
||||
void
|
||||
llarp_nodedb_async_load_rc(struct llarp_async_load_rc *job);
|
||||
struct llarp_async_load_rc
|
||||
{
|
||||
/// async_verify_context
|
||||
void *user;
|
||||
/// nodedb storage
|
||||
struct llarp_nodedb *nodedb;
|
||||
/// llarp_logic for calling hook
|
||||
struct llarp_logic *logic;
|
||||
/// disk worker threadpool
|
||||
struct llarp_threadpool *diskworker;
|
||||
/// target pubkey
|
||||
byte_t pubkey[PUBKEYSIZE];
|
||||
/// router contact result
|
||||
struct llarp_rc rc;
|
||||
/// set to true if we loaded the rc
|
||||
bool loaded;
|
||||
/// hook function called in logic thread
|
||||
llarp_async_load_rc_hook_func hook;
|
||||
};
|
||||
|
||||
/// asynchronously load an rc from disk
|
||||
void
|
||||
llarp_nodedb_async_load_rc(struct llarp_async_load_rc *job);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef LLARP_PATH_H
|
||||
#define LLARP_PATH_H
|
||||
|
||||
#include <llarp/router_contact.h>
|
||||
|
||||
#define MAXHOPS (8)
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
struct llarp_path_hops
|
||||
{
|
||||
struct llarp_rc routers[MAXHOPS];
|
||||
size_t numHops;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -1,5 +1,6 @@
|
|||
#ifndef LLARP_PATH_HPP
|
||||
#define LLARP_PATH_HPP
|
||||
#include <llarp/path.h>
|
||||
#include <llarp/router.h>
|
||||
#include <llarp/time.h>
|
||||
#include <llarp/aligned.hpp>
|
||||
|
@ -20,15 +21,14 @@ namespace llarp
|
|||
TransitHopInfo() = default;
|
||||
TransitHopInfo(const RouterID& down, const LR_CommitRecord& record);
|
||||
|
||||
PathID_t rxID;
|
||||
PathID_t txID;
|
||||
PathID_t pathID;
|
||||
RouterID upstream;
|
||||
RouterID downstream;
|
||||
|
||||
friend std::ostream&
|
||||
operator<<(std::ostream& out, const TransitHopInfo& info)
|
||||
{
|
||||
out << "<Transit Hop rxid=" << info.rxID << " txid=" << info.txID;
|
||||
out << "<Transit Hop id=" << info.pathID;
|
||||
out << " upstream=" << info.upstream << " downstream=" << info.downstream;
|
||||
return out << ">";
|
||||
}
|
||||
|
@ -36,8 +36,8 @@ namespace llarp
|
|||
bool
|
||||
operator==(const TransitHopInfo& other) const
|
||||
{
|
||||
return rxID == other.rxID && txID == other.txID
|
||||
&& upstream == other.upstream && downstream == other.downstream;
|
||||
return pathID == other.pathID && upstream == other.upstream
|
||||
&& downstream == other.downstream;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -46,41 +46,71 @@ namespace llarp
|
|||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool
|
||||
operator<(const TransitHopInfo& other) const
|
||||
{
|
||||
return pathID < other.pathID || upstream < other.upstream
|
||||
|| downstream < other.downstream;
|
||||
}
|
||||
|
||||
struct Hash
|
||||
{
|
||||
std::size_t
|
||||
operator()(TransitHopInfo const& a) const
|
||||
{
|
||||
std::size_t idx0, idx1, idx2, idx3;
|
||||
std::size_t idx0, idx1, idx2;
|
||||
memcpy(&idx0, a.upstream, sizeof(std::size_t));
|
||||
memcpy(&idx1, a.downstream, sizeof(std::size_t));
|
||||
memcpy(&idx2, a.rxID, sizeof(std::size_t));
|
||||
memcpy(&idx3, a.txID, sizeof(std::size_t));
|
||||
return idx0 ^ idx1 ^ idx2 ^ idx3;
|
||||
memcpy(&idx2, a.pathID, sizeof(std::size_t));
|
||||
return idx0 ^ idx1 ^ idx2;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
struct PathIDHash
|
||||
{
|
||||
std::size_t
|
||||
operator()(const PathID_t& a) const
|
||||
{
|
||||
std::size_t idx0;
|
||||
memcpy(&idx0, a, sizeof(std::size_t));
|
||||
return idx0;
|
||||
}
|
||||
};
|
||||
|
||||
struct TransitHop
|
||||
{
|
||||
TransitHop() = default;
|
||||
|
||||
SharedSecret rxKey;
|
||||
SharedSecret txKey;
|
||||
TransitHopInfo info;
|
||||
SharedSecret pathKey;
|
||||
llarp_time_t started;
|
||||
// 10 minutes default
|
||||
llarp_time_t lifetime = 360000;
|
||||
llarp_proto_version_t version;
|
||||
|
||||
bool
|
||||
Expired(llarp_time_t now) const;
|
||||
};
|
||||
|
||||
/// configuration for a single hop when building a path
|
||||
struct PathHopConfig
|
||||
{
|
||||
/// path id
|
||||
PathID_t txID;
|
||||
/// router identity key
|
||||
PubKey encryptionKey;
|
||||
PathID_t pathID;
|
||||
// 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;
|
||||
|
||||
~PathHopConfig();
|
||||
PathHopConfig();
|
||||
};
|
||||
|
||||
struct Path
|
||||
|
@ -88,19 +118,30 @@ namespace llarp
|
|||
typedef std::vector< PathHopConfig > HopList;
|
||||
HopList hops;
|
||||
llarp_time_t buildStarted;
|
||||
Path(llarp_path_hops* path);
|
||||
};
|
||||
|
||||
template < typename User >
|
||||
struct AsyncPathKeyExchangeContext
|
||||
{
|
||||
Path path;
|
||||
typedef void (*Handler)(AsyncPathKeyExchangeContext*);
|
||||
Path* path = nullptr;
|
||||
typedef void (*Handler)(AsyncPathKeyExchangeContext< User >*);
|
||||
User* user = nullptr;
|
||||
Handler result = nullptr;
|
||||
const byte_t* secretkey = nullptr;
|
||||
size_t idx = 0;
|
||||
llarp_threadpool* worker = nullptr;
|
||||
llarp_path_dh_func dh = nullptr;
|
||||
llarp_logic* logic = nullptr;
|
||||
llarp_crypto* crypto = nullptr;
|
||||
LR_CommitMessage LRCM;
|
||||
|
||||
static void
|
||||
HandleDone(void* user)
|
||||
{
|
||||
AsyncPathKeyExchangeContext< User >* ctx =
|
||||
static_cast< AsyncPathKeyExchangeContext< User >* >(user);
|
||||
ctx->result(ctx);
|
||||
delete ctx;
|
||||
}
|
||||
|
||||
static void
|
||||
GenerateNextKey(void* user)
|
||||
|
@ -108,38 +149,73 @@ namespace llarp
|
|||
AsyncPathKeyExchangeContext< User >* ctx =
|
||||
static_cast< AsyncPathKeyExchangeContext< User >* >(user);
|
||||
|
||||
auto& hop = ctx->path.hops[ctx->idx];
|
||||
ctx->dh(hop.shared, hop.encryptionKey, hop.nonce, ctx->secretkey);
|
||||
++ctx->idx;
|
||||
if(ctx->idx < ctx->path.hops.size())
|
||||
auto& hop = ctx->path->hops[ctx->idx];
|
||||
// generate key
|
||||
ctx->crypto->encryption_keygen(hop.commkey);
|
||||
// do key exchange
|
||||
if(!ctx->crypto->dh_client(hop.shared, hop.router.enckey, hop.nonce,
|
||||
hop.commkey))
|
||||
{
|
||||
llarp::Error("Failed to generate shared key for path build");
|
||||
delete ctx;
|
||||
return;
|
||||
}
|
||||
// randomize hop's path id
|
||||
hop.pathID.Randomize();
|
||||
|
||||
LR_CommitRecord record;
|
||||
|
||||
auto& frame = ctx->LRCM.frames[ctx->idx];
|
||||
++ctx->idx;
|
||||
if(ctx->idx < ctx->path->hops.size())
|
||||
{
|
||||
hop.upstream = ctx->path->hops[ctx->idx].router.pubkey;
|
||||
}
|
||||
else
|
||||
{
|
||||
hop.upstream = hop.router.pubkey;
|
||||
}
|
||||
// generate record
|
||||
if(!record.BEncode(frame.Buffer()))
|
||||
{
|
||||
// failed to encode?
|
||||
llarp::Error("Failed to generate Commit Record");
|
||||
delete ctx;
|
||||
return;
|
||||
}
|
||||
|
||||
if(ctx->idx < ctx->path->hops.size())
|
||||
{
|
||||
// next hop
|
||||
llarp_threadpool_queue_job(ctx->worker, {ctx, &GenerateNextKey});
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx->Done();
|
||||
// farthest hop
|
||||
llarp_logic_queue_job(ctx->logic, {ctx, &HandleDone});
|
||||
}
|
||||
}
|
||||
|
||||
AsyncPathKeyExchangeContext(const byte_t* secret, llarp_crypto* crypto)
|
||||
: secretkey(secret), dh(crypto->dh_client)
|
||||
AsyncPathKeyExchangeContext(llarp_crypto* c) : crypto(c)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Done()
|
||||
{
|
||||
idx = 0;
|
||||
result(this);
|
||||
}
|
||||
|
||||
/// Generate all keys asynchronously and call hadler when done
|
||||
void
|
||||
AsyncGenerateKeys(llarp_threadpool* pool, User* u, Handler func) const
|
||||
AsyncGenerateKeys(Path* p, llarp_logic* l, llarp_threadpool* pool, User* u,
|
||||
Handler func)
|
||||
{
|
||||
path = p;
|
||||
logic = l;
|
||||
user = u;
|
||||
result = func;
|
||||
worker = pool;
|
||||
|
||||
for(size_t idx = 0; idx < MAXHOPS; ++idx)
|
||||
{
|
||||
LRCM.frames.emplace_back(256);
|
||||
LRCM.frames.back().Randomize();
|
||||
}
|
||||
llarp_threadpool_queue_job(pool, {this, &GenerateNextKey});
|
||||
}
|
||||
};
|
||||
|
@ -206,76 +282,46 @@ namespace llarp
|
|||
PathContext(llarp_router* router);
|
||||
~PathContext();
|
||||
|
||||
/// called from router tick function
|
||||
void
|
||||
ExpirePaths();
|
||||
|
||||
void
|
||||
AllowTransit();
|
||||
void
|
||||
RejectTransit();
|
||||
|
||||
bool
|
||||
AllowingTransit() const;
|
||||
|
||||
bool
|
||||
HasTransitHop(const TransitHopInfo& info);
|
||||
|
||||
bool
|
||||
HandleRelayCommit(const LR_CommitMessage* msg);
|
||||
|
||||
void
|
||||
PutTransitHop(const TransitHop& hop);
|
||||
|
||||
bool
|
||||
HandleRelayAck(const LR_AckMessage* msg);
|
||||
ForwardLRCM(const RouterID& nextHop, std::deque< EncryptedFrame >& frames);
|
||||
|
||||
void
|
||||
PutPendingRelayCommit(const RouterID& router, const PathID_t& txid,
|
||||
const TransitHopInfo& info, const TransitHop& hop);
|
||||
ForwradLRUM(const PathID_t& id, const RouterID& from, llarp_buffer_t X,
|
||||
const TunnelNonce& nonce);
|
||||
|
||||
bool
|
||||
HasPendingRelayCommit(const RouterID& upstream, const PathID_t& txid);
|
||||
|
||||
bool
|
||||
ForwardLRCM(const RouterID& nextHop, std::deque< EncryptedFrame >& frames,
|
||||
std::deque< EncryptedAck >& acks, EncryptedFrame& lastFrame);
|
||||
void
|
||||
ForwradLRDM(const PathID_t& id, const RouterID& from, llarp_buffer_t X,
|
||||
const TunnelNonce& nonce);
|
||||
|
||||
bool
|
||||
HopIsUs(const PubKey& k) const;
|
||||
|
||||
typedef std::unordered_map< TransitHopInfo, TransitHop,
|
||||
TransitHopInfo::Hash >
|
||||
typedef std::unordered_multimap< PathID_t, TransitHop, PathIDHash >
|
||||
TransitHopsMap_t;
|
||||
|
||||
typedef std::pair< std::mutex, TransitHopsMap_t > SyncTransitMap_t;
|
||||
|
||||
struct PendingPathKey
|
||||
{
|
||||
RouterID upstream;
|
||||
PathID_t txID;
|
||||
|
||||
PendingPathKey(const RouterID& up, const PathID_t& id)
|
||||
: upstream(up), txID(id)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(const PendingPathKey& other) const
|
||||
{
|
||||
return upstream == other.upstream && txID == other.txID;
|
||||
}
|
||||
|
||||
struct Hash
|
||||
{
|
||||
std::size_t
|
||||
operator()(PendingPathKey const& a) const
|
||||
{
|
||||
std::size_t idx0, idx1;
|
||||
memcpy(&idx0, a.upstream, sizeof(std::size_t));
|
||||
memcpy(&idx1, a.txID, sizeof(std::size_t));
|
||||
return idx0 ^ idx1;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
typedef std::pair< TransitHopInfo, TransitHop > PendingCommit_t;
|
||||
|
||||
typedef std::pair< std::mutex,
|
||||
std::unordered_map< PendingPathKey, PendingCommit_t,
|
||||
PendingPathKey::Hash > >
|
||||
SyncPendingCommitMap_t;
|
||||
|
||||
llarp_threadpool*
|
||||
Worker();
|
||||
|
||||
|
@ -288,13 +334,15 @@ namespace llarp
|
|||
byte_t*
|
||||
EncryptionSecretKey();
|
||||
|
||||
const byte_t*
|
||||
OurRouterID() const;
|
||||
|
||||
private:
|
||||
llarp_router* m_Router;
|
||||
SyncTransitMap_t m_TransitPaths;
|
||||
SyncPendingCommitMap_t m_WaitingForAcks;
|
||||
|
||||
bool m_AllowTransit;
|
||||
};
|
||||
}
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
#ifndef LLARP_PATHFINDER_H_
|
||||
#define LLARP_PATHFINDER_H_
|
||||
|
||||
#include <llarp/buffer.h>
|
||||
#include <llarp/path.h>
|
||||
|
||||
/**
|
||||
* path_base.h
|
||||
*
|
||||
* path api functions
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/// forard declare
|
||||
struct llarp_router;
|
||||
struct llarp_dht_context;
|
||||
|
||||
// fwd declr
|
||||
struct llarp_pathbuilder_context;
|
||||
|
||||
/// alloc
|
||||
struct llarp_pathbuilder_context*
|
||||
llarp_pathbuilder_context_new(struct llarp_router* router,
|
||||
struct llarp_dht_context* dht);
|
||||
/// dealloc
|
||||
void
|
||||
llarp_pathbuilder_context_free(struct llarp_pathbuilder_context* ctx);
|
||||
|
||||
// fwd declr
|
||||
struct llarp_pathbuild_job;
|
||||
|
||||
/// response callback
|
||||
typedef void (*llarp_pathbuilder_hook)(struct llarp_pathbuild_job*);
|
||||
// select hop function (nodedb, result, hopnnumber) called in logic thread
|
||||
typedef void (*llarp_pathbuilder_select_hop_func)(struct llarp_nodedb*,
|
||||
struct llarp_rc*, size_t);
|
||||
|
||||
// request struct
|
||||
struct llarp_pathbuild_job
|
||||
{
|
||||
// opaque pointer for user data
|
||||
void* user;
|
||||
// router context (set by llarp_pathbuilder_build_path)
|
||||
struct llarp_router* router;
|
||||
// context
|
||||
struct llarp_pathbuilder_context* context;
|
||||
// path hop selection
|
||||
llarp_pathbuilder_select_hop_func selectHop;
|
||||
// result handler
|
||||
llarp_pathbuilder_hook result;
|
||||
// encryption secret key for hidden service
|
||||
byte_t* secretkey;
|
||||
// path
|
||||
struct llarp_path_hops hops;
|
||||
};
|
||||
|
||||
/// request func
|
||||
// or find_path but thought pathfinder_find_path was a bit redundant
|
||||
void
|
||||
llarp_pathbuilder_build_path(struct llarp_pathbuild_job* job);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -1,52 +0,0 @@
|
|||
#ifndef LLARP_PATHFINDER_H_
|
||||
#define LLARP_PATHFINDER_H_
|
||||
|
||||
#include <llarp/buffer.h>
|
||||
#include <llarp/router.h>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* path_base.h
|
||||
*
|
||||
* path api functions
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// fwd declr
|
||||
struct llarp_pathfinder_context;
|
||||
|
||||
/// alloc
|
||||
struct llarp_pathfinder_context *
|
||||
llarp_pathfinder_context_new(struct llarp_router* router,
|
||||
struct llarp_dht_context* dht);
|
||||
/// dealloc
|
||||
void
|
||||
llarp_pathfinder_context_free(struct llarp_pathfinder_context* ctx);
|
||||
|
||||
// fwd declr
|
||||
struct llarp_get_route;
|
||||
|
||||
/// response callback
|
||||
typedef void (*llarp_pathfinder_response)(struct llarp_get_route *);
|
||||
|
||||
// request struct
|
||||
struct llarp_get_route
|
||||
{
|
||||
// context
|
||||
struct llarp_pathfinder_context* pathfinder;
|
||||
// parameter
|
||||
byte_t destination[PUBKEYSIZE];
|
||||
// result
|
||||
std::vector<llarp_rc> route;
|
||||
};
|
||||
/// request func
|
||||
// or find_path but thought pathfinder_find_path was a bit redundant
|
||||
void llarp_pathfinder_get_route(struct llarp_pathfinder_context* pathfinder);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef LLARP_POW_HPP
|
||||
#define LLARP_POW_HPP
|
||||
#include <llarp/buffer.h>
|
||||
#include <llarp/crypto.h>
|
||||
#include <llarp/router_id.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
/// proof of work
|
||||
struct PoW
|
||||
{
|
||||
static constexpr size_t MaxSize = 128;
|
||||
|
||||
RouterID router;
|
||||
uint64_t version = 0;
|
||||
uint32_t extendedLifetime = 0;
|
||||
byte_t nonce[32];
|
||||
|
||||
bool
|
||||
BEncode(llarp_buffer_t* buf) const;
|
||||
|
||||
bool
|
||||
BDecode(llarp_buffer_t* buf);
|
||||
|
||||
bool
|
||||
IsValid(llarp_shorthash_func hashfunc, const RouterID& us) const;
|
||||
};
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
|
@ -5,6 +5,7 @@
|
|||
#include <llarp/link.h>
|
||||
#include <llarp/logic.h>
|
||||
#include <llarp/nodedb.h>
|
||||
#include <llarp/pathbuilder.h>
|
||||
#include <llarp/router_contact.h>
|
||||
#include <llarp/threadpool.h>
|
||||
|
||||
|
@ -28,6 +29,11 @@ bool
|
|||
llarp_router_try_connect(struct llarp_router *router, struct llarp_rc *remote,
|
||||
uint16_t numretries);
|
||||
|
||||
/// override default path builder function (FFI)
|
||||
void
|
||||
llarp_router_override_path_selection(struct llarp_router *router,
|
||||
llarp_pathbuilder_select_hop_func func);
|
||||
|
||||
bool
|
||||
llarp_configure_router(struct llarp_router *router, struct llarp_config *conf);
|
||||
|
||||
|
|
|
@ -384,100 +384,100 @@ namespace iwp
|
|||
frame->hook(frame);
|
||||
delete frame;
|
||||
}
|
||||
}
|
||||
} // namespace iwp
|
||||
|
||||
extern "C" {
|
||||
|
||||
void
|
||||
iwp_call_async_keygen(struct llarp_async_iwp *iwp,
|
||||
struct iwp_async_keygen *keygen)
|
||||
extern "C"
|
||||
{
|
||||
keygen->iwp = iwp;
|
||||
llarp_threadpool_queue_job(iwp->worker, {keygen, &iwp::keygen});
|
||||
}
|
||||
|
||||
void
|
||||
iwp_call_async_gen_intro(struct llarp_async_iwp *iwp,
|
||||
struct iwp_async_intro *intro)
|
||||
{
|
||||
intro->iwp = iwp;
|
||||
llarp_threadpool_queue_job(iwp->worker, {intro, &iwp::gen_intro});
|
||||
}
|
||||
|
||||
void
|
||||
iwp_call_async_verify_introack(struct llarp_async_iwp *iwp,
|
||||
struct iwp_async_introack *introack)
|
||||
{
|
||||
introack->iwp = iwp;
|
||||
llarp_threadpool_queue_job(iwp->worker, {introack, &iwp::verify_introack});
|
||||
}
|
||||
|
||||
void
|
||||
iwp_call_async_gen_session_start(struct llarp_async_iwp *iwp,
|
||||
struct iwp_async_session_start *session)
|
||||
{
|
||||
session->iwp = iwp;
|
||||
llarp_threadpool_queue_job(iwp->worker, {session, &iwp::gen_session_start});
|
||||
}
|
||||
|
||||
void
|
||||
iwp_call_async_verify_intro(struct llarp_async_iwp *iwp,
|
||||
struct iwp_async_intro *intro)
|
||||
{
|
||||
intro->iwp = iwp;
|
||||
llarp_threadpool_queue_job(iwp->worker, {intro, &iwp::verify_intro});
|
||||
}
|
||||
|
||||
void
|
||||
iwp_call_async_gen_introack(struct llarp_async_iwp *iwp,
|
||||
struct iwp_async_introack *introack)
|
||||
{
|
||||
introack->iwp = iwp;
|
||||
llarp_threadpool_queue_job(iwp->worker, {introack, &iwp::gen_introack});
|
||||
}
|
||||
|
||||
void
|
||||
iwp_call_async_frame_decrypt(struct llarp_async_iwp *iwp,
|
||||
struct iwp_async_frame *frame)
|
||||
{
|
||||
frame->iwp = iwp;
|
||||
llarp_threadpool_queue_job(iwp->worker, {frame, &iwp::hmac_then_decrypt});
|
||||
}
|
||||
|
||||
void
|
||||
iwp_call_async_frame_encrypt(struct llarp_async_iwp *iwp,
|
||||
struct iwp_async_frame *frame)
|
||||
{
|
||||
frame->iwp = iwp;
|
||||
llarp_threadpool_queue_job(iwp->worker, {frame, &iwp::encrypt_then_hmac});
|
||||
}
|
||||
|
||||
void
|
||||
iwp_call_async_verify_session_start(struct llarp_async_iwp *iwp,
|
||||
struct iwp_async_session_start *session)
|
||||
{
|
||||
session->iwp = iwp;
|
||||
llarp_threadpool_queue_job(iwp->worker,
|
||||
{session, &iwp::verify_session_start});
|
||||
}
|
||||
|
||||
struct llarp_async_iwp *
|
||||
llarp_async_iwp_new(struct llarp_crypto *crypto, struct llarp_logic *logic,
|
||||
struct llarp_threadpool *worker)
|
||||
{
|
||||
llarp_async_iwp *iwp = new llarp_async_iwp;
|
||||
if(iwp)
|
||||
void
|
||||
iwp_call_async_keygen(struct llarp_async_iwp *iwp,
|
||||
struct iwp_async_keygen *keygen)
|
||||
{
|
||||
iwp->crypto = crypto;
|
||||
iwp->logic = logic;
|
||||
iwp->worker = worker;
|
||||
keygen->iwp = iwp;
|
||||
llarp_threadpool_queue_job(iwp->worker, {keygen, &iwp::keygen});
|
||||
}
|
||||
return iwp;
|
||||
}
|
||||
|
||||
void
|
||||
llarp_async_iwp_free(struct llarp_async_iwp *iwp)
|
||||
{
|
||||
delete iwp;
|
||||
}
|
||||
void
|
||||
iwp_call_async_gen_intro(struct llarp_async_iwp *iwp,
|
||||
struct iwp_async_intro *intro)
|
||||
{
|
||||
intro->iwp = iwp;
|
||||
llarp_threadpool_queue_job(iwp->worker, {intro, &iwp::gen_intro});
|
||||
}
|
||||
|
||||
void
|
||||
iwp_call_async_verify_introack(struct llarp_async_iwp *iwp,
|
||||
struct iwp_async_introack *introack)
|
||||
{
|
||||
introack->iwp = iwp;
|
||||
llarp_threadpool_queue_job(iwp->worker, {introack, &iwp::verify_introack});
|
||||
}
|
||||
|
||||
void
|
||||
iwp_call_async_gen_session_start(struct llarp_async_iwp *iwp,
|
||||
struct iwp_async_session_start *session)
|
||||
{
|
||||
session->iwp = iwp;
|
||||
llarp_threadpool_queue_job(iwp->worker, {session, &iwp::gen_session_start});
|
||||
}
|
||||
|
||||
void
|
||||
iwp_call_async_verify_intro(struct llarp_async_iwp *iwp,
|
||||
struct iwp_async_intro *intro)
|
||||
{
|
||||
intro->iwp = iwp;
|
||||
llarp_threadpool_queue_job(iwp->worker, {intro, &iwp::verify_intro});
|
||||
}
|
||||
|
||||
void
|
||||
iwp_call_async_gen_introack(struct llarp_async_iwp *iwp,
|
||||
struct iwp_async_introack *introack)
|
||||
{
|
||||
introack->iwp = iwp;
|
||||
llarp_threadpool_queue_job(iwp->worker, {introack, &iwp::gen_introack});
|
||||
}
|
||||
|
||||
void
|
||||
iwp_call_async_frame_decrypt(struct llarp_async_iwp *iwp,
|
||||
struct iwp_async_frame *frame)
|
||||
{
|
||||
frame->iwp = iwp;
|
||||
llarp_threadpool_queue_job(iwp->worker, {frame, &iwp::hmac_then_decrypt});
|
||||
}
|
||||
|
||||
void
|
||||
iwp_call_async_frame_encrypt(struct llarp_async_iwp *iwp,
|
||||
struct iwp_async_frame *frame)
|
||||
{
|
||||
frame->iwp = iwp;
|
||||
llarp_threadpool_queue_job(iwp->worker, {frame, &iwp::encrypt_then_hmac});
|
||||
}
|
||||
|
||||
void
|
||||
iwp_call_async_verify_session_start(struct llarp_async_iwp *iwp,
|
||||
struct iwp_async_session_start *session)
|
||||
{
|
||||
session->iwp = iwp;
|
||||
llarp_threadpool_queue_job(iwp->worker,
|
||||
{session, &iwp::verify_session_start});
|
||||
}
|
||||
|
||||
struct llarp_async_iwp *
|
||||
llarp_async_iwp_new(struct llarp_crypto *crypto, struct llarp_logic *logic,
|
||||
struct llarp_threadpool *worker)
|
||||
{
|
||||
llarp_async_iwp *iwp = new llarp_async_iwp;
|
||||
if(iwp)
|
||||
{
|
||||
iwp->crypto = crypto;
|
||||
iwp->logic = logic;
|
||||
iwp->worker = worker;
|
||||
}
|
||||
return iwp;
|
||||
}
|
||||
|
||||
void
|
||||
llarp_async_iwp_free(struct llarp_async_iwp *iwp)
|
||||
{
|
||||
delete iwp;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <llarp/crypto.hpp>
|
||||
#include <llarp/encrypted_frame.hpp>
|
||||
#include "logger.hpp"
|
||||
#include "mem.hpp"
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
|
@ -10,6 +11,8 @@ namespace llarp
|
|||
data = new byte_t[sz];
|
||||
if(buf)
|
||||
memcpy(data, buf, sz);
|
||||
else
|
||||
llarp::Zero(data, sz);
|
||||
m_Buffer.base = data;
|
||||
m_Buffer.cur = data;
|
||||
m_Buffer.sz = size;
|
||||
|
@ -87,7 +90,8 @@ namespace llarp
|
|||
{
|
||||
if(size <= size_t(EncryptedFrame::OverheadSize))
|
||||
{
|
||||
llarp::Warn("encrypted frame too small, ", size, " <= ", size_t(EncryptedFrame::OverheadSize));
|
||||
llarp::Warn("encrypted frame too small, ", size,
|
||||
" <= ", size_t(EncryptedFrame::OverheadSize));
|
||||
return false;
|
||||
}
|
||||
// format of frame is
|
||||
|
@ -143,4 +147,4 @@ namespace llarp
|
|||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} // namespace llarp
|
||||
|
|
207
llarp/path.cpp
207
llarp/path.cpp
|
@ -5,6 +5,15 @@
|
|||
|
||||
namespace llarp
|
||||
{
|
||||
Path::Path(llarp_path_hops* h)
|
||||
{
|
||||
for(size_t idx = 0; idx < h->numHops; ++idx)
|
||||
{
|
||||
hops.emplace_back();
|
||||
llarp_rc_copy(&hops[idx].router, &h->routers[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
PathContext::PathContext(llarp_router* router)
|
||||
: m_Router(router), m_AllowTransit(false)
|
||||
{
|
||||
|
@ -20,136 +29,10 @@ namespace llarp
|
|||
m_AllowTransit = true;
|
||||
}
|
||||
|
||||
struct LRCMFrameDecrypt
|
||||
{
|
||||
typedef AsyncFrameDecrypter< LRCMFrameDecrypt > Decrypter;
|
||||
Decrypter* decrypter;
|
||||
std::deque< EncryptedFrame > frames;
|
||||
std::deque< EncryptedAck > acks;
|
||||
EncryptedFrame lastFrame;
|
||||
PathContext* context;
|
||||
RouterID from;
|
||||
LR_CommitRecord record;
|
||||
TransitHopInfo info;
|
||||
TransitHop hop;
|
||||
|
||||
LRCMFrameDecrypt(PathContext* ctx, Decrypter* dec,
|
||||
const LR_CommitMessage* commit)
|
||||
: decrypter(dec)
|
||||
, lastFrame(commit->lasthopFrame)
|
||||
, context(ctx)
|
||||
, from(commit->remote)
|
||||
{
|
||||
for(const auto& f : commit->frames)
|
||||
frames.push_front(f);
|
||||
for(const auto& a : commit->acks)
|
||||
acks.push_front(a);
|
||||
}
|
||||
|
||||
~LRCMFrameDecrypt()
|
||||
{
|
||||
delete decrypter;
|
||||
}
|
||||
|
||||
static void
|
||||
AcceptLRCM(void* user)
|
||||
{
|
||||
LRCMFrameDecrypt* self = static_cast< LRCMFrameDecrypt* >(user);
|
||||
llarp::Info("Accepted ", self->info);
|
||||
self->context->PutPendingRelayCommit(self->info.upstream, self->info.txID,
|
||||
self->info, self->hop);
|
||||
size_t sz = self->frames.front().size;
|
||||
// we pop the front element it was ours
|
||||
self->frames.pop_front();
|
||||
// put random on the end
|
||||
// TODO: should this be an encrypted frame?
|
||||
// TODO: should we change the size?
|
||||
self->frames.emplace_back(sz);
|
||||
self->frames.back().Randomize();
|
||||
self->context->ForwardLRCM(self->info.upstream, self->frames, self->acks,
|
||||
self->lastFrame);
|
||||
delete self;
|
||||
}
|
||||
|
||||
static void
|
||||
HandleDecrypted(llarp_buffer_t* buf, LRCMFrameDecrypt* self)
|
||||
{
|
||||
if(!buf)
|
||||
{
|
||||
llarp::Error("LRCM decrypt failed from ", self->from);
|
||||
delete self;
|
||||
return;
|
||||
}
|
||||
llarp::Debug("decrypted LRCM from ", self->from);
|
||||
// successful decrypt
|
||||
if(!self->record.BDecode(buf))
|
||||
{
|
||||
llarp::Error("malformed frame inside LRCM from ", self->from);
|
||||
delete self;
|
||||
return;
|
||||
}
|
||||
self->info = TransitHopInfo(self->from, self->record);
|
||||
if(self->context->HasTransitHop(self->info))
|
||||
{
|
||||
llarp::Error("duplicate transit hop ", self->info);
|
||||
delete self;
|
||||
return;
|
||||
}
|
||||
// choose rx id
|
||||
// TODO: check for duplicates
|
||||
self->info.rxID.Randomize();
|
||||
|
||||
// generate tx key as we are in a worker thread
|
||||
auto DH = self->context->Crypto()->dh_server;
|
||||
if(!DH(self->hop.txKey, self->record.commkey,
|
||||
self->context->EncryptionSecretKey(), self->record.tunnelNonce))
|
||||
{
|
||||
llarp::Error("LRCM DH Failed ", self->info);
|
||||
delete self;
|
||||
return;
|
||||
}
|
||||
if(self->context->HopIsUs(self->record.nextHop))
|
||||
{
|
||||
// we are the farthest hop
|
||||
llarp::Info("We are the farthest hop for ", self->info);
|
||||
// TODO: implement
|
||||
delete self;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: generate rx path
|
||||
|
||||
// forward upstream
|
||||
// XXX: we are still in the worker thread so post job to logic
|
||||
llarp_logic_queue_job(self->context->Logic(), {self, &AcceptLRCM});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
PathContext::HandleRelayCommit(const LR_CommitMessage* commit)
|
||||
PathContext::AllowingTransit() const
|
||||
{
|
||||
if(!m_AllowTransit)
|
||||
{
|
||||
llarp::Error("got LRCM from ", commit->remote,
|
||||
" when not allowing transit traffic");
|
||||
return false;
|
||||
}
|
||||
if(commit->frames.size() <= 1)
|
||||
{
|
||||
llarp::Error("got LRCM with too few frames from ", commit->remote);
|
||||
return false;
|
||||
}
|
||||
LRCMFrameDecrypt::Decrypter* decrypter =
|
||||
new LRCMFrameDecrypt::Decrypter(&m_Router->crypto, m_Router->encryption,
|
||||
&LRCMFrameDecrypt::HandleDecrypted);
|
||||
// copy frames so we own them
|
||||
LRCMFrameDecrypt* frames = new LRCMFrameDecrypt(this, decrypter, commit);
|
||||
|
||||
// decrypt frames async
|
||||
decrypter->AsyncDecrypt(m_Router->tp, &frames->frames.front(), frames);
|
||||
|
||||
return true;
|
||||
return m_AllowTransit;
|
||||
}
|
||||
|
||||
llarp_threadpool*
|
||||
|
@ -184,9 +67,7 @@ namespace llarp
|
|||
|
||||
bool
|
||||
PathContext::ForwardLRCM(const RouterID& nextHop,
|
||||
std::deque< EncryptedFrame >& frames,
|
||||
std::deque< EncryptedAck >& acks,
|
||||
EncryptedFrame& lastHop)
|
||||
std::deque< EncryptedFrame >& frames)
|
||||
{
|
||||
LR_CommitMessage* msg = new LR_CommitMessage;
|
||||
while(frames.size())
|
||||
|
@ -194,21 +75,22 @@ namespace llarp
|
|||
msg->frames.push_back(frames.back());
|
||||
frames.pop_back();
|
||||
}
|
||||
while(acks.size())
|
||||
{
|
||||
msg->acks.push_back(acks.back());
|
||||
acks.pop_back();
|
||||
}
|
||||
msg->lasthopFrame = lastHop;
|
||||
return m_Router->SendToOrQueue(nextHop, {msg});
|
||||
}
|
||||
|
||||
template < typename Map_t, typename Value_t >
|
||||
template < typename Map_t, typename Key_t, typename CheckValue_t >
|
||||
bool
|
||||
MapHas(Map_t& map, const Value_t& val)
|
||||
MapHas(Map_t& map, const Key_t& k, CheckValue_t check)
|
||||
{
|
||||
std::unique_lock< std::mutex > lock(map.first);
|
||||
return map.second.find(val) != map.second.end();
|
||||
auto itr = map.second.find(k);
|
||||
while(itr != map.second.end())
|
||||
{
|
||||
if(check(itr->second))
|
||||
return true;
|
||||
++itr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template < typename Map_t, typename Key_t, typename Value_t >
|
||||
|
@ -216,35 +98,54 @@ namespace llarp
|
|||
MapPut(Map_t& map, const Key_t& k, const Value_t& v)
|
||||
{
|
||||
std::unique_lock< std::mutex > lock(map.first);
|
||||
map.second[k] = v;
|
||||
map.second.emplace(k, v);
|
||||
}
|
||||
|
||||
bool
|
||||
PathContext::HasTransitHop(const TransitHopInfo& info)
|
||||
{
|
||||
return MapHas(m_TransitPaths, info);
|
||||
return MapHas(
|
||||
m_TransitPaths, info.pathID,
|
||||
[info](const TransitHop& hop) -> bool { return info == hop.info; });
|
||||
}
|
||||
|
||||
const byte_t*
|
||||
PathContext::OurRouterID() const
|
||||
{
|
||||
return m_Router->pubkey();
|
||||
}
|
||||
|
||||
void
|
||||
PathContext::PutPendingRelayCommit(const RouterID& upstream,
|
||||
const PathID_t& txid,
|
||||
const TransitHopInfo& info,
|
||||
const TransitHop& hop)
|
||||
PathContext::PutTransitHop(const TransitHop& hop)
|
||||
{
|
||||
MapPut(m_WaitingForAcks, PendingPathKey(upstream, txid),
|
||||
std::make_pair(info, hop));
|
||||
MapPut(m_TransitPaths, hop.info.pathID, 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();
|
||||
while(itr != map.end())
|
||||
{
|
||||
if(itr->second.Expired(now))
|
||||
itr = map.erase(itr);
|
||||
else
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
PathContext::HasPendingRelayCommit(const RouterID& upstream,
|
||||
const PathID_t& txid)
|
||||
TransitHop::Expired(llarp_time_t now) const
|
||||
{
|
||||
return MapHas(m_WaitingForAcks, PendingPathKey(upstream, txid));
|
||||
return now - started > lifetime;
|
||||
}
|
||||
|
||||
TransitHopInfo::TransitHopInfo(const RouterID& down,
|
||||
const LR_CommitRecord& record)
|
||||
: txID(record.txid), upstream(record.nextHop), downstream(down)
|
||||
: pathID(record.pathid), upstream(record.nextHop), downstream(down)
|
||||
{
|
||||
}
|
||||
}
|
||||
} // namespace llarp
|
|
@ -0,0 +1,84 @@
|
|||
#include <llarp/nodedb.h>
|
||||
#include <llarp/path.hpp>
|
||||
|
||||
#include "pathbuilder.hpp"
|
||||
#include "router.hpp"
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
PathHopConfig::PathHopConfig()
|
||||
{
|
||||
llarp_rc_clear(&router);
|
||||
}
|
||||
|
||||
PathHopConfig::~PathHopConfig()
|
||||
{
|
||||
llarp_rc_free(&router);
|
||||
}
|
||||
|
||||
void
|
||||
pathbuilder_generated_keys(
|
||||
AsyncPathKeyExchangeContext< llarp_pathbuild_job >* ctx)
|
||||
{
|
||||
llarp::Debug("Generated keys for build");
|
||||
}
|
||||
|
||||
void
|
||||
pathbuilder_start_build(void* user)
|
||||
{
|
||||
// select hops
|
||||
llarp_pathbuild_job* job = static_cast< llarp_pathbuild_job* >(user);
|
||||
size_t idx = 0;
|
||||
while(idx < job->hops.numHops)
|
||||
{
|
||||
job->selectHop(job->router->nodedb, &job->hops.routers[idx], idx);
|
||||
++idx;
|
||||
}
|
||||
|
||||
// async generate keys
|
||||
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);
|
||||
// free rc
|
||||
idx = 0;
|
||||
while(idx < job->hops.numHops)
|
||||
{
|
||||
llarp_rc_free(&job->hops.routers[idx]);
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
} // namespace llarp
|
||||
|
||||
llarp_pathbuilder_context::llarp_pathbuilder_context(
|
||||
llarp_router* p_router, struct llarp_dht_context* p_dht)
|
||||
{
|
||||
this->router = p_router;
|
||||
this->dht = p_dht;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
struct llarp_pathbuilder_context*
|
||||
llarp_pathbuilder_context_new(struct llarp_router* router,
|
||||
struct llarp_dht_context* dht)
|
||||
{
|
||||
return new llarp_pathbuilder_context(router, dht);
|
||||
}
|
||||
|
||||
void
|
||||
llarp_pathbuilder_context_free(struct llarp_pathbuilder_context* ctx)
|
||||
{
|
||||
delete ctx;
|
||||
}
|
||||
|
||||
void
|
||||
llarp_pathbuilder_build_path(struct llarp_pathbuild_job* job)
|
||||
{
|
||||
job->router = job->context->router;
|
||||
llarp_logic_queue_job(job->router->logic,
|
||||
{job, &llarp::pathbuilder_start_build});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef LLARP_PATHFINDER_HPP_
|
||||
#define LLARP_PATHFINDER_HPP_
|
||||
#include <llarp/pathbuilder.h>
|
||||
|
||||
struct llarp_pathbuilder_context
|
||||
{
|
||||
struct llarp_router* router;
|
||||
struct llarp_dht_context* dht;
|
||||
/// copy cstr
|
||||
llarp_pathbuilder_context(llarp_router* p_router,
|
||||
struct llarp_dht_context* p_dht);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,28 +1,2 @@
|
|||
#include "pathfinder.hpp"
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
|
||||
void llarp_pathfinder_get_route(struct llarp_pathfinder_context* pathfinder) {
|
||||
// what thread do pathfinder run in?
|
||||
}
|
||||
}
|
||||
|
||||
llarp_pathfinder_context::llarp_pathfinder_context(llarp_router *p_router, struct llarp_dht_context* p_dht)
|
||||
{
|
||||
this->router = p_router;
|
||||
this->dht = p_dht;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
struct llarp_pathfinder_context *
|
||||
llarp_pathfinder_context_new(struct llarp_router* router,
|
||||
struct llarp_dht_context* dht) {
|
||||
return new llarp_pathfinder_context(router, dht);
|
||||
}
|
||||
|
||||
void
|
||||
llarp_pathfinder_context_free(struct llarp_pathfinder_context* ctx) {
|
||||
delete ctx;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
#ifndef LLARP_PATHFINDER_HPP_
|
||||
#define LLARP_PATHFINDER_HPP_
|
||||
#include <llarp/pathfinder.h>
|
||||
|
||||
struct llarp_pathfinder_context {
|
||||
struct llarp_router* router;
|
||||
struct llarp_dht_context* dht;
|
||||
/// copy cstr
|
||||
llarp_pathfinder_context(llarp_router *p_router, struct llarp_dht_context* p_dht);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,47 @@
|
|||
#include <cmath>
|
||||
#include <llarp/pow.hpp>
|
||||
#include "buffer.hpp"
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
bool
|
||||
PoW::BDecode(llarp_buffer_t* buf)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
PoW::BEncode(llarp_buffer_t* buf) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
PoW::IsValid(llarp_shorthash_func hashfunc, const RouterID& us) const
|
||||
{
|
||||
// is it for us?
|
||||
if(router != us)
|
||||
return false;
|
||||
byte_t digest[SHORTHASHSIZE];
|
||||
byte_t tmp[MaxSize];
|
||||
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
|
||||
// encode
|
||||
if(!BEncode(&buf))
|
||||
return false;
|
||||
// rewind
|
||||
buf.sz = buf.cur - buf.base;
|
||||
buf.cur = buf.base;
|
||||
// hash
|
||||
if(!hashfunc(digest, buf))
|
||||
return false;
|
||||
// check bytes required
|
||||
uint32_t required = std::floor(std::log(extendedLifetime));
|
||||
for(uint32_t idx = 0; idx < required; ++idx)
|
||||
{
|
||||
if(digest[idx])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace llarp
|
|
@ -77,14 +77,8 @@ namespace llarp
|
|||
bool
|
||||
LR_AckMessage::HandleMessage(llarp_router* router) const
|
||||
{
|
||||
if(!router->paths.HasPendingRelayCommit(remote, txPathID))
|
||||
{
|
||||
llarp::Warn("got LRAM from ", remote,
|
||||
" with no previous LRCM txid=", txPathID);
|
||||
return false;
|
||||
}
|
||||
// TODO: use different private key for different path contexts as client
|
||||
LRAM_Decrypt* lram = new LRAM_Decrypt(router, router->encryption, acks);
|
||||
LRAM_Decrypt* lram = new LRAM_Decrypt(router, router->encryption, replies);
|
||||
lram->decrypt->AsyncDecrypt(router->tp, &lram->frames[0], lram);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,24 @@
|
|||
|
||||
namespace llarp
|
||||
{
|
||||
bool
|
||||
LR_AcceptRecord::BEncode(llarp_buffer_t* buf) const
|
||||
{
|
||||
if(!bencode_start_dict(buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictMsgType(buf, "c", "a"))
|
||||
return false;
|
||||
if(!BEncodeWriteDictEntry("p", pathid, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictEntry("r", downstream, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictEntry("t", upstream, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictInt(buf, "v", LLARP_PROTO_VERSION))
|
||||
return false;
|
||||
return bencode_end(buf);
|
||||
}
|
||||
|
||||
LR_CommitMessage::~LR_CommitMessage()
|
||||
{
|
||||
}
|
||||
|
@ -16,14 +34,6 @@ namespace llarp
|
|||
{
|
||||
return BEncodeReadList(frames, buf);
|
||||
}
|
||||
if(llarp_buffer_eq(key, "f"))
|
||||
{
|
||||
return lasthopFrame.BDecode(buf);
|
||||
}
|
||||
if(llarp_buffer_eq(key, "r"))
|
||||
{
|
||||
return BEncodeReadList(acks, buf);
|
||||
}
|
||||
bool read = false;
|
||||
if(!BEncodeMaybeReadVersion("v", version, LLARP_PROTO_VERSION, read, key,
|
||||
buf))
|
||||
|
@ -43,12 +53,6 @@ namespace llarp
|
|||
// frames
|
||||
if(!BEncodeWriteDictList("c", frames, buf))
|
||||
return false;
|
||||
// last hop
|
||||
if(!BEncodeWriteDictEntry("f", lasthopFrame, buf))
|
||||
return false;
|
||||
// acks
|
||||
if(!BEncodeWriteDictList("r", acks, buf))
|
||||
return false;
|
||||
// version
|
||||
if(!bencode_write_version_entry(buf))
|
||||
return false;
|
||||
|
@ -59,7 +63,19 @@ namespace llarp
|
|||
bool
|
||||
LR_CommitMessage::HandleMessage(llarp_router* router) const
|
||||
{
|
||||
return router->paths.HandleRelayCommit(this);
|
||||
if(frames.size() != MAXHOPS)
|
||||
{
|
||||
llarp::Error("LRCM invalid number of records, ", frames.size(),
|
||||
"!=", MAXHOPS);
|
||||
return false;
|
||||
}
|
||||
if(!router->paths.AllowingTransit())
|
||||
{
|
||||
llarp::Error("got an LRCM from ", remote,
|
||||
" when we are not allowing transit");
|
||||
return false;
|
||||
}
|
||||
return AsyncDecrypt(&router->paths);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -74,18 +90,22 @@ namespace llarp
|
|||
return false;
|
||||
if(!BEncodeWriteDictEntry("n", tunnelNonce, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictEntry("p", txid, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictEntry("s", downstreamReplyKey, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictEntry("u", downstreamReplyNonce, buf))
|
||||
if(!BEncodeWriteDictEntry("p", pathid, buf))
|
||||
return false;
|
||||
if(!bencode_write_version_entry(buf))
|
||||
return false;
|
||||
if(work && !BEncodeWriteDictEntry("w", *work, buf))
|
||||
return false;
|
||||
|
||||
return bencode_end(buf);
|
||||
}
|
||||
|
||||
LR_CommitRecord::~LR_CommitRecord()
|
||||
{
|
||||
if(work)
|
||||
delete work;
|
||||
}
|
||||
|
||||
bool
|
||||
LR_CommitRecord::OnKey(dict_reader* r, llarp_buffer_t* key)
|
||||
{
|
||||
|
@ -102,18 +122,20 @@ namespace llarp
|
|||
return false;
|
||||
if(BEncodeMaybeReadDictEntry("n", self->tunnelNonce, read, *key, r->buffer))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictEntry("p", self->txid, read, *key, r->buffer))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictEntry("s", self->downstreamReplyKey, read, *key,
|
||||
r->buffer))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictEntry("u", self->downstreamReplyNonce, read, *key,
|
||||
r->buffer))
|
||||
if(!BEncodeMaybeReadDictEntry("p", self->pathid, read, *key, r->buffer))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadVersion("v", self->version, LLARP_PROTO_VERSION, read,
|
||||
*key, r->buffer))
|
||||
return false;
|
||||
if(llarp_buffer_eq(*key, "w"))
|
||||
{
|
||||
// check for duplicate
|
||||
if(self->work)
|
||||
return false;
|
||||
|
||||
self->work = new PoW;
|
||||
return self->work->BDecode(r->buffer);
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
|
@ -125,4 +147,154 @@ namespace llarp
|
|||
r.on_key = &OnKey;
|
||||
return bencode_read_dict(buf, &r);
|
||||
}
|
||||
}
|
||||
|
||||
struct LRCMFrameDecrypt
|
||||
{
|
||||
typedef AsyncFrameDecrypter< LRCMFrameDecrypt > Decrypter;
|
||||
Decrypter* decrypter;
|
||||
std::deque< EncryptedFrame > frames;
|
||||
PathContext* context;
|
||||
// decrypted record
|
||||
LR_CommitRecord record;
|
||||
// the actual hop
|
||||
TransitHop hop;
|
||||
|
||||
LRCMFrameDecrypt(PathContext* ctx, Decrypter* dec,
|
||||
const LR_CommitMessage* commit)
|
||||
: decrypter(dec), context(ctx)
|
||||
{
|
||||
for(const auto& f : commit->frames)
|
||||
frames.push_front(f);
|
||||
hop.info.downstream = commit->remote;
|
||||
}
|
||||
|
||||
~LRCMFrameDecrypt()
|
||||
{
|
||||
delete decrypter;
|
||||
}
|
||||
|
||||
/// this must be done from logic thread
|
||||
static void
|
||||
SendLRCM(void* user)
|
||||
{
|
||||
LRCMFrameDecrypt* self = static_cast< LRCMFrameDecrypt* >(user);
|
||||
self->context->ForwardLRCM(self->hop.info.upstream, self->frames);
|
||||
delete self;
|
||||
}
|
||||
|
||||
static void
|
||||
SendLRAM(void* user)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
HandleDecrypted(llarp_buffer_t* buf, LRCMFrameDecrypt* self)
|
||||
{
|
||||
auto& info = self->hop.info;
|
||||
if(!buf)
|
||||
{
|
||||
llarp::Error("LRCM decrypt failed from ", info.downstream);
|
||||
delete self;
|
||||
return;
|
||||
}
|
||||
llarp::Debug("decrypted LRCM from ", info.downstream);
|
||||
// successful decrypt
|
||||
if(!self->record.BDecode(buf))
|
||||
{
|
||||
llarp::Error("malformed frame inside LRCM from ", info.downstream);
|
||||
delete self;
|
||||
return;
|
||||
}
|
||||
|
||||
info.pathID = self->record.pathid;
|
||||
info.upstream = self->record.nextHop;
|
||||
if(self->context->HasTransitHop(info))
|
||||
{
|
||||
llarp::Error("duplicate transit hop ", info);
|
||||
delete self;
|
||||
return;
|
||||
}
|
||||
// generate path key as we are in a worker thread
|
||||
auto DH = self->context->Crypto()->dh_server;
|
||||
if(!DH(self->hop.pathKey, self->record.commkey,
|
||||
self->context->EncryptionSecretKey(), self->record.tunnelNonce))
|
||||
{
|
||||
llarp::Error("LRCM DH Failed ", info);
|
||||
delete self;
|
||||
return;
|
||||
}
|
||||
if(self->record.work
|
||||
&& self->record.work->IsValid(self->context->Crypto()->shorthash,
|
||||
self->context->OurRouterID()))
|
||||
{
|
||||
llarp::Info("LRCM extended lifetime by ",
|
||||
self->record.work->extendedLifetime, " seconds for ", info);
|
||||
self->hop.lifetime += 1000 * self->record.work->extendedLifetime;
|
||||
}
|
||||
|
||||
// TODO: check if we really want to accept it
|
||||
self->hop.started = llarp_time_now_ms();
|
||||
llarp::Info("Accepted ", self->hop.info);
|
||||
self->context->PutTransitHop(self->hop);
|
||||
|
||||
size_t sz = self->frames.front().size;
|
||||
// we pop the front element it was ours
|
||||
self->frames.pop_front();
|
||||
// put our response on the end
|
||||
self->frames.emplace_back(sz);
|
||||
auto& reply = self->frames.back();
|
||||
auto replybuf = reply.Buffer();
|
||||
LR_AcceptRecord replyrecord;
|
||||
replyrecord.upstream = info.upstream;
|
||||
replyrecord.downstream = info.downstream;
|
||||
replyrecord.pathid = info.pathID;
|
||||
if(!replyrecord.BEncode(replybuf))
|
||||
{
|
||||
llarp::Error("failed to encode reply to LRCM, buffer too small?");
|
||||
delete self;
|
||||
return;
|
||||
}
|
||||
// randomize leftover data inside reply
|
||||
auto left = llarp_buffer_size_left(*replybuf);
|
||||
if(left)
|
||||
self->context->Crypto()->randbytes(replybuf->cur, left);
|
||||
|
||||
// encrypt in place since we are in the worker thread
|
||||
if(!reply.EncryptInPlace(self->context->EncryptionSecretKey(),
|
||||
self->record.commkey, self->context->Crypto()))
|
||||
{
|
||||
// failed to encrypt wtf?
|
||||
llarp::Error("Failed to encrypt reply to LRCM");
|
||||
delete self;
|
||||
return;
|
||||
}
|
||||
if(self->context->HopIsUs(info.upstream))
|
||||
{
|
||||
// we are the farthest hop
|
||||
llarp::Info("We are the farthest hop for ", info);
|
||||
// send a LRAM down the path
|
||||
llarp_logic_queue_job(self->context->Logic(), {self, &SendLRAM});
|
||||
}
|
||||
else
|
||||
{
|
||||
// forward upstream
|
||||
// we are still in the worker thread so post job to logic
|
||||
llarp_logic_queue_job(self->context->Logic(), {self, &SendLRCM});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
LR_CommitMessage::AsyncDecrypt(PathContext* context) const
|
||||
{
|
||||
LRCMFrameDecrypt::Decrypter* decrypter = new LRCMFrameDecrypt::Decrypter(
|
||||
context->Crypto(), context->EncryptionSecretKey(),
|
||||
&LRCMFrameDecrypt::HandleDecrypted);
|
||||
// copy frames so we own them
|
||||
LRCMFrameDecrypt* frames = new LRCMFrameDecrypt(context, decrypter, this);
|
||||
|
||||
// decrypt frames async
|
||||
decrypter->AsyncDecrypt(context->Worker(), &frames->frames.front(), frames);
|
||||
return true;
|
||||
}
|
||||
} // namespace llarp
|
||||
|
|
370
llarp/router.cpp
370
llarp/router.cpp
|
@ -363,6 +363,9 @@ void
|
|||
llarp_router::Tick()
|
||||
{
|
||||
llarp::Debug("tick router");
|
||||
paths.ExpirePaths();
|
||||
llarp_pathbuild_job job;
|
||||
llarp_pathbuilder_build_path(&job);
|
||||
llarp_link_session_iter iter;
|
||||
iter.user = this;
|
||||
iter.visit = &send_padded_message;
|
||||
|
@ -627,30 +630,6 @@ llarp_router::ConnectAll(void *user, uint64_t orig, uint64_t left)
|
|||
self->try_connect(itr.second);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
struct llarp_router *
|
||||
llarp_init_router(struct llarp_threadpool *tp, struct llarp_ev_loop *netloop,
|
||||
struct llarp_logic *logic)
|
||||
{
|
||||
llarp_router *router = new llarp_router();
|
||||
if(router)
|
||||
{
|
||||
router->netloop = netloop;
|
||||
router->tp = tp;
|
||||
router->logic = logic;
|
||||
// TODO: make disk io threadpool count configurable
|
||||
#ifdef TESTNET
|
||||
router->disk = tp;
|
||||
#else
|
||||
router->disk = llarp_init_threadpool(1, "llarp-diskio");
|
||||
#endif
|
||||
llarp_crypto_libsodium_init(&router->crypto);
|
||||
}
|
||||
return router;
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_router::InitOutboundLink()
|
||||
{
|
||||
|
@ -686,185 +665,216 @@ llarp_router::InitOutboundLink()
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_configure_router(struct llarp_router *router, struct llarp_config *conf)
|
||||
{
|
||||
llarp_config_iterator iter;
|
||||
iter.user = router;
|
||||
iter.visit = llarp::router_iter_config;
|
||||
llarp_config_iter(conf, &iter);
|
||||
if(!router->InitOutboundLink())
|
||||
return false;
|
||||
if(!router->Ready())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return router->EnsureIdentity();
|
||||
}
|
||||
|
||||
void
|
||||
llarp_run_router(struct llarp_router *router, struct llarp_nodedb *nodedb)
|
||||
{
|
||||
router->nodedb = nodedb;
|
||||
router->Run();
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_router::HasPendingConnectJob(const llarp::RouterID &remote)
|
||||
{
|
||||
return pendingEstablishJobs.find(remote) != pendingEstablishJobs.end();
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_router_try_connect(struct llarp_router *router, struct llarp_rc *remote,
|
||||
uint16_t numretries)
|
||||
extern "C"
|
||||
{
|
||||
// do we already have a pending job for this remote?
|
||||
if(router->HasPendingConnectJob(remote->pubkey))
|
||||
return false;
|
||||
// try first address only
|
||||
llarp_ai addr;
|
||||
if(llarp_ai_list_index(remote->addrs, 0, &addr))
|
||||
struct llarp_router *
|
||||
llarp_init_router(struct llarp_threadpool *tp, struct llarp_ev_loop *netloop,
|
||||
struct llarp_logic *logic)
|
||||
{
|
||||
auto link = router->outboundLink;
|
||||
auto itr = router->pendingEstablishJobs.emplace(
|
||||
std::make_pair(remote->pubkey, llarp_link_establish_job{}));
|
||||
auto job = &itr.first->second;
|
||||
llarp_ai_copy(&job->ai, &addr);
|
||||
memcpy(job->pubkey, remote->pubkey, PUBKEYSIZE);
|
||||
job->retries = numretries;
|
||||
job->timeout = 10000;
|
||||
job->result = &llarp_router::on_try_connect_result;
|
||||
// give router as user pointer
|
||||
job->user = router;
|
||||
// try establishing
|
||||
link->try_establish(link, job);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
llarp_rc_clear(struct llarp_rc *rc)
|
||||
{
|
||||
// zero out router contact
|
||||
llarp::Zero(rc, sizeof(llarp_rc));
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_rc_addr_list_iter(struct llarp_ai_list_iter *iter, struct llarp_ai *ai)
|
||||
{
|
||||
struct llarp_rc *rc = (llarp_rc *)iter->user;
|
||||
llarp_ai_list_pushback(rc->addrs, ai);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
llarp_rc_set_addrs(struct llarp_rc *rc, struct llarp_alloc *mem,
|
||||
struct llarp_ai_list *addr)
|
||||
{
|
||||
rc->addrs = llarp_ai_list_new();
|
||||
struct llarp_ai_list_iter ai_itr;
|
||||
ai_itr.user = rc;
|
||||
ai_itr.visit = &llarp_rc_addr_list_iter;
|
||||
llarp_ai_list_iterate(addr, &ai_itr);
|
||||
}
|
||||
|
||||
void
|
||||
llarp_rc_set_pubkey(struct llarp_rc *rc, const uint8_t *pubkey)
|
||||
{
|
||||
// set public key
|
||||
memcpy(rc->pubkey, pubkey, 32);
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_findOrCreateIdentity(llarp_crypto *crypto, const char *fpath,
|
||||
byte_t *secretkey)
|
||||
{
|
||||
llarp::Debug("find or create ", fpath);
|
||||
fs::path path(fpath);
|
||||
std::error_code ec;
|
||||
if(!fs::exists(path, ec))
|
||||
{
|
||||
llarp::Info("regenerated identity key");
|
||||
crypto->identity_keygen(secretkey);
|
||||
std::ofstream f(path, std::ios::binary);
|
||||
if(f.is_open())
|
||||
llarp_router *router = new llarp_router();
|
||||
if(router)
|
||||
{
|
||||
f.write((char *)secretkey, SECKEYSIZE);
|
||||
router->netloop = netloop;
|
||||
router->tp = tp;
|
||||
router->logic = logic;
|
||||
// TODO: make disk io threadpool count configurable
|
||||
#ifdef TESTNET
|
||||
router->disk = tp;
|
||||
#else
|
||||
router->disk = llarp_init_threadpool(1, "llarp-diskio");
|
||||
#endif
|
||||
llarp_crypto_libsodium_init(&router->crypto);
|
||||
}
|
||||
return router;
|
||||
}
|
||||
std::ifstream f(path, std::ios::binary);
|
||||
if(f.is_open())
|
||||
{
|
||||
f.read((char *)secretkey, SECKEYSIZE);
|
||||
return true;
|
||||
}
|
||||
llarp::Info("failed to get identity key");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_rc_write(struct llarp_rc *rc, const char *fpath)
|
||||
{
|
||||
fs::path our_rc_file(fpath);
|
||||
byte_t tmp[MAX_RC_SIZE];
|
||||
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
|
||||
|
||||
if(llarp_rc_bencode(rc, &buf))
|
||||
bool
|
||||
llarp_configure_router(struct llarp_router *router, struct llarp_config *conf)
|
||||
{
|
||||
std::ofstream f(our_rc_file, std::ios::binary);
|
||||
if(f.is_open())
|
||||
llarp_config_iterator iter;
|
||||
iter.user = router;
|
||||
iter.visit = llarp::router_iter_config;
|
||||
llarp_config_iter(conf, &iter);
|
||||
if(!router->InitOutboundLink())
|
||||
return false;
|
||||
if(!router->Ready())
|
||||
{
|
||||
f.write((char *)buf.base, buf.cur - buf.base);
|
||||
return false;
|
||||
}
|
||||
return router->EnsureIdentity();
|
||||
}
|
||||
|
||||
void
|
||||
llarp_run_router(struct llarp_router *router, struct llarp_nodedb *nodedb)
|
||||
{
|
||||
router->nodedb = nodedb;
|
||||
router->Run();
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_router_try_connect(struct llarp_router *router, struct llarp_rc *remote,
|
||||
uint16_t numretries)
|
||||
{
|
||||
// do we already have a pending job for this remote?
|
||||
if(router->HasPendingConnectJob(remote->pubkey))
|
||||
return false;
|
||||
// try first address only
|
||||
llarp_ai addr;
|
||||
if(llarp_ai_list_index(remote->addrs, 0, &addr))
|
||||
{
|
||||
auto link = router->outboundLink;
|
||||
auto itr = router->pendingEstablishJobs.emplace(
|
||||
std::make_pair(remote->pubkey, llarp_link_establish_job{}));
|
||||
auto job = &itr.first->second;
|
||||
llarp_ai_copy(&job->ai, &addr);
|
||||
memcpy(job->pubkey, remote->pubkey, PUBKEYSIZE);
|
||||
job->retries = numretries;
|
||||
job->timeout = 10000;
|
||||
job->result = &llarp_router::on_try_connect_result;
|
||||
// give router as user pointer
|
||||
job->user = router;
|
||||
// try establishing
|
||||
link->try_establish(link, job);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
llarp_rc_sign(llarp_crypto *crypto, const byte_t *seckey, struct llarp_rc *rc)
|
||||
{
|
||||
byte_t buf[MAX_RC_SIZE];
|
||||
auto signbuf = llarp::StackBuffer< decltype(buf) >(buf);
|
||||
// zero out previous signature
|
||||
llarp::Zero(rc->signature, sizeof(rc->signature));
|
||||
// encode
|
||||
if(llarp_rc_bencode(rc, &signbuf))
|
||||
void
|
||||
llarp_rc_clear(struct llarp_rc *rc)
|
||||
{
|
||||
// sign
|
||||
signbuf.sz = signbuf.cur - signbuf.base;
|
||||
crypto->sign(rc->signature, seckey, signbuf);
|
||||
// zero out router contact
|
||||
llarp::Zero(rc, sizeof(llarp_rc));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
llarp_stop_router(struct llarp_router *router)
|
||||
{
|
||||
if(router)
|
||||
router->Close();
|
||||
}
|
||||
|
||||
void
|
||||
llarp_router_iterate_links(struct llarp_router *router,
|
||||
struct llarp_router_link_iter i)
|
||||
{
|
||||
for(auto link : router->inboundLinks)
|
||||
if(!i.visit(&i, router, link))
|
||||
return;
|
||||
i.visit(&i, router, router->outboundLink);
|
||||
}
|
||||
|
||||
void
|
||||
llarp_free_router(struct llarp_router **router)
|
||||
{
|
||||
if(*router)
|
||||
bool
|
||||
llarp_rc_addr_list_iter(struct llarp_ai_list_iter *iter, struct llarp_ai *ai)
|
||||
{
|
||||
delete *router;
|
||||
struct llarp_rc *rc = (llarp_rc *)iter->user;
|
||||
llarp_ai_list_pushback(rc->addrs, ai);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
llarp_rc_set_addrs(struct llarp_rc *rc, struct llarp_alloc *mem,
|
||||
struct llarp_ai_list *addr)
|
||||
{
|
||||
rc->addrs = llarp_ai_list_new();
|
||||
struct llarp_ai_list_iter ai_itr;
|
||||
ai_itr.user = rc;
|
||||
ai_itr.visit = &llarp_rc_addr_list_iter;
|
||||
llarp_ai_list_iterate(addr, &ai_itr);
|
||||
}
|
||||
|
||||
void
|
||||
llarp_rc_set_pubkey(struct llarp_rc *rc, const uint8_t *pubkey)
|
||||
{
|
||||
// set public key
|
||||
memcpy(rc->pubkey, pubkey, 32);
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_findOrCreateIdentity(llarp_crypto *crypto, const char *fpath,
|
||||
byte_t *secretkey)
|
||||
{
|
||||
llarp::Debug("find or create ", fpath);
|
||||
fs::path path(fpath);
|
||||
std::error_code ec;
|
||||
if(!fs::exists(path, ec))
|
||||
{
|
||||
llarp::Info("regenerated identity key");
|
||||
crypto->identity_keygen(secretkey);
|
||||
std::ofstream f(path, std::ios::binary);
|
||||
if(f.is_open())
|
||||
{
|
||||
f.write((char *)secretkey, SECKEYSIZE);
|
||||
}
|
||||
}
|
||||
std::ifstream f(path, std::ios::binary);
|
||||
if(f.is_open())
|
||||
{
|
||||
f.read((char *)secretkey, SECKEYSIZE);
|
||||
return true;
|
||||
}
|
||||
llarp::Info("failed to get identity key");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_rc_write(struct llarp_rc *rc, const char *fpath)
|
||||
{
|
||||
fs::path our_rc_file(fpath);
|
||||
byte_t tmp[MAX_RC_SIZE];
|
||||
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
|
||||
|
||||
if(llarp_rc_bencode(rc, &buf))
|
||||
{
|
||||
std::ofstream f(our_rc_file, std::ios::binary);
|
||||
if(f.is_open())
|
||||
{
|
||||
f.write((char *)buf.base, buf.cur - buf.base);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
llarp_rc_sign(llarp_crypto *crypto, const byte_t *seckey, struct llarp_rc *rc)
|
||||
{
|
||||
byte_t buf[MAX_RC_SIZE];
|
||||
auto signbuf = llarp::StackBuffer< decltype(buf) >(buf);
|
||||
// zero out previous signature
|
||||
llarp::Zero(rc->signature, sizeof(rc->signature));
|
||||
// encode
|
||||
if(llarp_rc_bencode(rc, &signbuf))
|
||||
{
|
||||
// sign
|
||||
signbuf.sz = signbuf.cur - signbuf.base;
|
||||
crypto->sign(rc->signature, seckey, signbuf);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
llarp_stop_router(struct llarp_router *router)
|
||||
{
|
||||
if(router)
|
||||
router->Close();
|
||||
}
|
||||
|
||||
void
|
||||
llarp_router_iterate_links(struct llarp_router *router,
|
||||
struct llarp_router_link_iter i)
|
||||
{
|
||||
for(auto link : router->inboundLinks)
|
||||
if(!i.visit(&i, router, link))
|
||||
return;
|
||||
i.visit(&i, router, router->outboundLink);
|
||||
}
|
||||
|
||||
void
|
||||
llarp_free_router(struct llarp_router **router)
|
||||
{
|
||||
if(*router)
|
||||
{
|
||||
delete *router;
|
||||
}
|
||||
*router = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
llarp_router_override_path_selection(struct llarp_router *router,
|
||||
llarp_pathbuilder_select_hop_func func)
|
||||
{
|
||||
if(func)
|
||||
router->selectHopFunc = func;
|
||||
}
|
||||
*router = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
namespace llarp
|
||||
|
|
|
@ -71,6 +71,8 @@ struct llarp_router
|
|||
|
||||
llarp::InboundMessageParser inbound_msg_parser;
|
||||
|
||||
llarp_pathbuilder_select_hop_func selectHopFunc = nullptr;
|
||||
|
||||
llarp_link *outboundLink = nullptr;
|
||||
std::list< llarp_link * > inboundLinks;
|
||||
|
||||
|
|
Loading…
Reference in New Issue