pull/1/head
Ryan Tharp 6 years ago
commit 7d2aa9b036

@ -32,7 +32,7 @@ else()
endif() endif()
set(DEBUG_FLAGS "-g") set(DEBUG_FLAGS "-g")
set(OPTIMIZE_FLAGS "-Os") set(OPTIMIZE_FLAGS "-O0")
if(ASAN) if(ASAN)
set(DEBUG_FLAGS "${DEBUG_FLAGS} -fsanitize=address -fno-omit-frame-pointer") set(DEBUG_FLAGS "${DEBUG_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
@ -155,6 +155,7 @@ set(LIB_SRC
set(TEST_SRC set(TEST_SRC
test/main.cpp test/main.cpp
test/dht_unittest.cpp test/dht_unittest.cpp
test/encrypted_frame_unittest.cpp
) )
set(TEST_EXE testAll) set(TEST_EXE testAll)
set(GTEST_DIR test/gtest) set(GTEST_DIR test/gtest)

@ -59,10 +59,9 @@ shadow: shadow-build
bash -c "$(SHADOW_BIN) -w $$(cat /proc/cpuinfo | grep processor | wc -l) $(SHADOW_CONFIG) &> $(SHADOW_LOG) || true" bash -c "$(SHADOW_BIN) -w $$(cat /proc/cpuinfo | grep processor | wc -l) $(SHADOW_CONFIG) &> $(SHADOW_LOG) || true"
testnet-configure: clean testnet-configure: clean
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug cmake -GNinja -DCMAKE_BUILD_TYPE=Debug
testnet-build: testnet-configure testnet-build: testnet-configure
ninja clean
ninja ninja
testnet: testnet-build testnet: testnet-build
@ -71,6 +70,7 @@ testnet: testnet-build
supervisord -n -d $(TESTNET_ROOT) -l $(TESTNET_LOG) -c $(TESTNET_CONF) supervisord -n -d $(TESTNET_ROOT) -l $(TESTNET_LOG) -c $(TESTNET_CONF)
test: debug-configure test: debug-configure
ninja
ninja test ninja test
format: format:

@ -6,25 +6,34 @@ import os
from xml.etree import ElementTree as etree from xml.etree import ElementTree as etree
getSetting = lambda s, name, fallback : name in s and s[name] or fallback
shadowRoot = getSetting(os.environ, "SHADOW_ROOT", os.path.join(os.environ['HOME'], '.shadow')) def getSetting(s, name, fallback): return name in s and s[name] or fallback
shadowRoot = getSetting(os.environ, "SHADOW_ROOT",
os.path.join(os.environ['HOME'], '.shadow'))
libpath = 'libshadow-plugin-llarp.so' libpath = 'libshadow-plugin-llarp.so'
def nodeconf(conf, baseDir, name, ifname=None, port=None): def nodeconf(conf, baseDir, name, ifname=None, port=None):
conf['netdb'] = {'dir': 'tmp-nodes'} conf['netdb'] = {'dir': 'tmp-nodes'}
conf['router'] = {} conf['router'] = {}
conf['router']['contact-file'] = os.path.join(baseDir, '{}.signed'.format(name)) conf['router']['contact-file'] = os.path.join(
conf['router']['ident-privkey'] = os.path.join(baseDir, '{}-ident.key'.format(name)) baseDir, '{}.signed'.format(name))
conf['router']['transport-privkey'] = os.path.join(baseDir, '{}-transport.key'.format(name)) conf['router']['ident-privkey'] = os.path.join(
baseDir, '{}-ident.key'.format(name))
conf['router']['transport-privkey'] = os.path.join(
baseDir, '{}-transport.key'.format(name))
if ifname and port: if ifname and port:
conf['bind'] = {ifname: port} conf['bind'] = {ifname: port}
conf['connect'] = {} conf['connect'] = {}
def addPeer(conf, baseDir, peer): def addPeer(conf, baseDir, peer):
conf['connect'][peer] = os.path.join(baseDir, '{}.signed'.format(peer)) conf['connect'][peer] = os.path.join(baseDir, '{}.signed'.format(peer))
def createNode(pluginName, root, peer): def createNode(pluginName, root, peer):
node = etree.SubElement(root, 'node') node = etree.SubElement(root, 'node')
node.attrib['id'] = peer['name'] node.attrib['id'] = peer['name']
@ -38,39 +47,42 @@ def createNode(pluginName, root, peer):
def makeBase(settings, name, id): def makeBase(settings, name, id):
return { return {
'id': id, 'id': id,
'name' : name, 'name': name,
'contact-file' : os.path.join(getSetting(settings, 'baseDir', 'tmp'), '{}.signed'.format(name)), 'contact-file': os.path.join(getSetting(settings, 'baseDir', 'tmp'), '{}.signed'.format(name)),
'configfile' : os.path.join(getSetting(settings, 'baseDir', 'tmp'), '{}.ini'.format(name)), 'configfile': os.path.join(getSetting(settings, 'baseDir', 'tmp'), '{}.ini'.format(name)),
'config': configparser.ConfigParser() 'config': configparser.ConfigParser()
} }
def makeClient(settings, name, id): def makeClient(settings, name, id):
peer = makeBase(settings, name, id) peer = makeBase(settings, name, id)
nodeconf(peer['config'], getSetting(settings, 'baseDir', 'tmp'), name) nodeconf(peer['config'], getSetting(settings, 'baseDir', 'tmp'), name)
return peer return peer
def makeSVCNode(settings, name, id, port): def makeSVCNode(settings, name, id, port):
peer = makeBase(settings, name, id) peer = makeBase(settings, name, id)
nodeconf(peer['config'], getSetting(settings, 'baseDir', 'tmp'), name, 'eth0', port) nodeconf(peer['config'], getSetting(
settings, 'baseDir', 'tmp'), name, 'eth0', port)
return peer return peer
def genconf(settings, outf): def genconf(settings, outf):
root = etree.Element('shadow') root = etree.Element('shadow')
topology = etree.SubElement(root, 'topology') topology = etree.SubElement(root, 'topology')
topology.attrib['path'] = getSetting(settings, 'topology', os.path.join(shadowRoot, 'share', 'topology.graphml.xml')) topology.attrib['path'] = getSetting(settings, 'topology', os.path.join(
shadowRoot, 'share', 'topology.graphml.xml'))
pluginName = getSetting(settings, 'name', 'llarpd') pluginName = getSetting(settings, 'name', 'llarpd')
kill = etree.SubElement(root, 'kill') kill = etree.SubElement(root, 'kill')
kill.attrib['time'] = getSetting(settings, 'runFor', '600') kill.attrib['time'] = getSetting(settings, 'runFor', '600')
baseDir = getSetting(settings, 'baseDir', 'tmp') baseDir = getSetting(settings, 'baseDir', 'tmp')
if not os.path.exists(baseDir): if not os.path.exists(baseDir):
os.mkdir(baseDir) os.mkdir(baseDir)
plugin = etree.SubElement(root, "plugin") plugin = etree.SubElement(root, "plugin")
plugin.attrib['id'] = pluginName plugin.attrib['id'] = pluginName
plugin.attrib['path'] = libpath plugin.attrib['path'] = libpath
@ -78,7 +90,8 @@ def genconf(settings, outf):
svcNodeCount = getSetting(settings, 'service-nodes', 20) svcNodeCount = getSetting(settings, 'service-nodes', 20)
peers = list() peers = list()
for nodeid in range(svcNodeCount): for nodeid in range(svcNodeCount):
peers.append(makeSVCNode(settings, 'svc-node-{}'.format(nodeid), str(nodeid), basePort + 1)) peers.append(makeSVCNode(
settings, 'svc-node-{}'.format(nodeid), str(nodeid), basePort + 1))
basePort += 1 basePort += 1
# make all service nodes know each other # make all service nodes know each other
@ -86,14 +99,15 @@ def genconf(settings, outf):
for nodeid in range(svcNodeCount): for nodeid in range(svcNodeCount):
if str(nodeid) != peer['id']: if str(nodeid) != peer['id']:
addPeer(peer['config'], baseDir, 'svc-node-{}'.format(nodeid)) addPeer(peer['config'], baseDir, 'svc-node-{}'.format(nodeid))
# add client nodes # add client nodes
for nodeid in range(getSetting(settings, 'client-nodes', 200)): for nodeid in range(getSetting(settings, 'client-nodes', 200)):
peer = makeClient(settings, 'client-node-{}'.format(nodeid), str(nodeid)) peer = makeClient(
settings, 'client-node-{}'.format(nodeid), str(nodeid))
peers.append(peer) peers.append(peer)
for p in range(getSetting(settings, 'client-connect-to', 3)): for p in range(getSetting(settings, 'client-connect-to', 10)):
addPeer(peer['config'], baseDir, 'svc-node-{}'.format((p + nodeid) % svcNodeCount)) addPeer(peer['config'], baseDir,
'svc-node-{}'.format((p + nodeid) % svcNodeCount))
# generate xml and settings files # generate xml and settings files
for peer in peers: for peer in peers:
@ -105,9 +119,10 @@ def genconf(settings, outf):
# render # render
outf.write(etree.tostring(root).decode('utf-8')) outf.write(etree.tostring(root).decode('utf-8'))
if __name__ == '__main__': if __name__ == '__main__':
settings = { settings = {
'topology': os.path.join(shadowRoot, 'share', 'topology.graphml.xml') 'topology': os.path.join(shadowRoot, 'share', 'topology.graphml.xml')
} }
with open(sys.argv[1], 'w') as f: with open(sys.argv[1], 'w') as f:
genconf(settings, f) genconf(settings, f)

@ -9,37 +9,44 @@ from configparser import ConfigParser as CP
import os import os
svcNodeName = lambda id : 'svc-node-%03d' % id
clientNodeName = lambda id : 'client-node-%03d' % id def svcNodeName(id): return 'svc-node-%03d' % id
def clientNodeName(id): return 'client-node-%03d' % id
def main(): def main():
ap = AP() ap = AP()
ap.add_argument('--dir', type=str, default='testnet_tmp') ap.add_argument('--dir', type=str, default='testnet_tmp')
ap.add_argument('--svc', type=int, default=20, help='number of service nodes') ap.add_argument('--svc', type=int, default=20,
help='number of service nodes')
ap.add_argument('--baseport', type=int, default=19000) ap.add_argument('--baseport', type=int, default=19000)
ap.add_argument('--clients', type=int, default=200, help='number of client nodes') ap.add_argument('--clients', type=int, default=200,
help='number of client nodes')
ap.add_argument('--bin', type=str, required=True) ap.add_argument('--bin', type=str, required=True)
ap.add_argument('--out', type=str, required=True) ap.add_argument('--out', type=str, required=True)
ap.add_argument('--connect', type=int, default=5) ap.add_argument('--connect', type=int, default=10)
args = ap.parse_args() args = ap.parse_args()
basedir = os.path.abspath(args.dir) basedir = os.path.abspath(args.dir)
for nodeid in range(args.svc): for nodeid in range(args.svc):
config = CP() config = CP()
config['bind'] = { config['bind'] = {
'lo' : str(args.baseport + nodeid) 'lo': str(args.baseport + nodeid)
} }
config['netdb'] = { config['netdb'] = {
'dir' : 'netdb' 'dir': 'netdb'
} }
config['connect'] = {} config['connect'] = {}
for otherid in range(args.svc): for otherid in range(args.svc):
if otherid != nodeid: if otherid != nodeid:
name = svcNodeName(otherid) name = svcNodeName(otherid)
config['connect'][name] = os.path.join(basedir, name, 'rc.signed') config['connect'][name] = os.path.join(
basedir, name, 'rc.signed')
d = os.path.join(args.dir, svcNodeName(nodeid)) d = os.path.join(args.dir, svcNodeName(nodeid))
if not os.path.exists(d): if not os.path.exists(d):
os.mkdir(d) os.mkdir(d)
@ -50,22 +57,22 @@ def main():
for nodeid in range(args.clients): for nodeid in range(args.clients):
config = CP() config = CP()
config['netdb'] = { config['netdb'] = {
'dir' : 'netdb' 'dir': 'netdb'
} }
config['connect'] = {} config['connect'] = {}
for otherid in range(args.svc): for otherid in range(args.connect):
if otherid % args.connect == 0: otherid = (nodeid + otherid) % args.svc
name = svcNodeName(otherid) name = svcNodeName(otherid)
config['connect'][name] = os.path.join(basedir, name, 'rc.signed') config['connect'][name] = os.path.join(
basedir, name, 'rc.signed')
d = os.path.join(args.dir, clientNodeName(nodeid)) d = os.path.join(args.dir, clientNodeName(nodeid))
if not os.path.exists(d): if not os.path.exists(d):
os.mkdir(d) os.mkdir(d)
fp = os.path.join(d, 'daemon.ini') fp = os.path.join(d, 'daemon.ini')
with open(fp, 'w') as f: with open(fp, 'w') as f:
config.write(f) config.write(f)
with open(args.out, 'w') as f: with open(args.out, 'w') as f:
f.write('''[program:svc-node] f.write('''[program:svc-node]
directory = {} directory = {}
@ -86,6 +93,7 @@ process_name = client-node-%(process_num)03d
numprocs = {} numprocs = {}
'''.format(os.path.join(args.dir, 'client-node-%(process_num)03d'), args.bin, args.clients)) '''.format(os.path.join(args.dir, 'client-node-%(process_num)03d'), args.bin, args.clients))
f.write('[supervisord]\ndirectory=.\n') f.write('[supervisord]\ndirectory=.\n')
if __name__ == '__main__': if __name__ == '__main__':
main() main()

@ -26,6 +26,7 @@ extern "C" {
#define SIGSIZE 64 #define SIGSIZE 64
#define TUNNONCESIZE 32 #define TUNNONCESIZE 32
#define HMACSIZE 32 #define HMACSIZE 32
#define PATHIDSIZE 16
/* /*
typedef byte_t llarp_pubkey_t[PUBKEYSIZE]; typedef byte_t llarp_pubkey_t[PUBKEYSIZE];
@ -42,7 +43,7 @@ typedef byte_t llarp_tunnel_nonce_t[TUNNONCESIZE];
/// label functors /// label functors
/// PKE(result, publickey, nonce, secretkey) /// PKE(result, publickey, secretkey, nonce)
typedef bool (*llarp_path_dh_func)(byte_t *, byte_t *, byte_t *, byte_t *); typedef bool (*llarp_path_dh_func)(byte_t *, byte_t *, byte_t *, byte_t *);
/// TKE(result publickey, secretkey, nonce) /// TKE(result publickey, secretkey, nonce)

@ -4,6 +4,7 @@
#include <llarp/bencode.h> #include <llarp/bencode.h>
#include <llarp/buffer.h> #include <llarp/buffer.h>
#include <sodium.h> #include <sodium.h>
#include <vector>
namespace llarp namespace llarp
{ {
@ -13,19 +14,24 @@ namespace llarp
Encrypted() = default; Encrypted() = default;
Encrypted(const byte_t* buf, size_t sz); Encrypted(const byte_t* buf, size_t sz);
Encrypted(size_t sz); Encrypted(size_t sz);
~Encrypted();
bool bool
BEncode(llarp_buffer_t* buf) const BEncode(llarp_buffer_t* buf) const
{ {
return bencode_write_bytestring(buf, data, size); return bencode_write_bytestring(buf, _data.data(), _data.size());
}
void
Fill(byte_t fill)
{
std::fill(_data.begin(), _data.end(), fill);
} }
void void
Randomize() Randomize()
{ {
if(data) if(_data.size())
randombytes(data, size); randombytes(_data.data(), _data.size());
} }
bool bool
@ -36,11 +42,8 @@ namespace llarp
return false; return false;
if(strbuf.sz == 0) if(strbuf.sz == 0)
return false; return false;
if(data) _data.resize(strbuf.sz);
delete[] data; memcpy(_data.data(), strbuf.base, _data.size());
size = strbuf.sz;
data = new byte_t[size];
memcpy(data, strbuf.base, size);
return true; return true;
} }
@ -50,12 +53,29 @@ namespace llarp
return &m_Buffer; return &m_Buffer;
} }
byte_t* data = nullptr; size_t
size_t size = 0; size()
{
return _data.size();
}
size_t
size() const
{
return _data.size();
}
byte_t*
data()
{
return _data.data();
}
std::vector< byte_t > _data;
private: private:
llarp_buffer_t m_Buffer; llarp_buffer_t m_Buffer;
}; };
} } // namespace llarp
#endif #endif

@ -44,7 +44,6 @@ namespace llarp
ctx->handler(ctx->frame, ctx->user); ctx->handler(ctx->frame, ctx->user);
else else
{ {
delete ctx->frame;
ctx->handler(nullptr, ctx->user); ctx->handler(nullptr, ctx->user);
} }
} }
@ -68,8 +67,8 @@ namespace llarp
// TODO: should we own otherKey? // TODO: should we own otherKey?
otherKey = other; otherKey = other;
frame = new EncryptedFrame(buf.sz); frame = new EncryptedFrame(buf.sz);
memcpy(frame->data + PUBKEYSIZE + TUNNONCESIZE + SHORTHASHSIZE, buf.base, memcpy(frame->data() + PUBKEYSIZE + TUNNONCESIZE + SHORTHASHSIZE,
buf.sz); buf.base, buf.sz);
user = u; user = u;
llarp_threadpool_queue_job(worker, {this, &Encrypt}); llarp_threadpool_queue_job(worker, {this, &Encrypt});
} }
@ -103,6 +102,7 @@ namespace llarp
llarp_crypto* crypto; llarp_crypto* crypto;
byte_t* seckey; byte_t* seckey;
EncryptedFrame* target; EncryptedFrame* target;
void void
AsyncDecrypt(llarp_threadpool* worker, EncryptedFrame* frame, User* user) AsyncDecrypt(llarp_threadpool* worker, EncryptedFrame* frame, User* user)
{ {

@ -0,0 +1,18 @@
#ifndef LLARP_ENDPOINT_HANDLER_HPP
#define LLARP_ENDPOINT_HANDLER_HPP
#include <llarp/buffer.h>
namespace llarp
{
// hidden service endpoint handler
struct IEndpointHandler
{
~IEndpointHandler(){};
virtual void
HandleMessage(llarp_buffer_t buf) = 0;
};
} // namespace llarp
#endif

@ -90,7 +90,7 @@ namespace llarp
_glog.out << "\n" << std::flush; _glog.out << "\n" << std::flush;
#endif #endif
} }
} } // namespace llarp
#define Debug(x, ...) _Log(llarp::eLogDebug, __FILE__, x, ##__VA_ARGS__) #define Debug(x, ...) _Log(llarp::eLogDebug, __FILE__, x, ##__VA_ARGS__)
#define Info(x, ...) _Log(llarp::eLogInfo, __FILE__, x, ##__VA_ARGS__) #define Info(x, ...) _Log(llarp::eLogInfo, __FILE__, x, ##__VA_ARGS__)

@ -54,8 +54,13 @@ llarp_nodedb_get_random_rc(struct llarp_nodedb *n, struct llarp_rc *result);
/// select a random rc at hop number N /// select a random rc at hop number N
void void
llarp_nodedb_select_random_hop(struct llarp_nodedb *n, struct llarp_rc *result, llarp_nodedb_select_random_hop(struct llarp_nodedb *n, struct llarp_rc *prev,
size_t N); struct llarp_rc *result, size_t N);
/// return number of RC loaded
size_t
llarp_nodedb_num_loaded(struct llarp_nodedb *n);
/** /**
put an rc into the node db put an rc into the node db
overwrites with new contents if already present overwrites with new contents if already present

@ -8,12 +8,23 @@
extern "C" { extern "C" {
#endif #endif
struct llarp_path_hop
{
struct llarp_rc router;
byte_t nextHop[PUBKEYSIZE];
byte_t sessionkey[SHAREDKEYSIZE];
byte_t pathid[PATHIDSIZE];
};
struct llarp_path_hops struct llarp_path_hops
{ {
struct llarp_rc routers[MAXHOPS]; struct llarp_path_hop hops[MAXHOPS];
size_t numHops; size_t numHops;
}; };
void
llarp_path_hops_free(struct llarp_path_hops* hops);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -5,11 +5,14 @@
#include <llarp/time.h> #include <llarp/time.h>
#include <llarp/aligned.hpp> #include <llarp/aligned.hpp>
#include <llarp/crypto.hpp> #include <llarp/crypto.hpp>
#include <llarp/endpoint.hpp>
#include <llarp/messages/relay_ack.hpp> #include <llarp/messages/relay_ack.hpp>
#include <llarp/messages/relay_commit.hpp> #include <llarp/messages/relay_commit.hpp>
#include <llarp/path_types.hpp> #include <llarp/path_types.hpp>
#include <llarp/router_id.hpp> #include <llarp/router_id.hpp>
#include <list>
#include <map>
#include <mutex> #include <mutex>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
@ -91,6 +94,14 @@ namespace llarp
bool bool
Expired(llarp_time_t now) const; Expired(llarp_time_t now) const;
// forward data in upstream direction
void
ForwardUpstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r);
// forward data in downstream direction
void
ForwardDownstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r);
}; };
/// configuration for a single hop when building a path /// configuration for a single hop when building a path
@ -113,12 +124,35 @@ namespace llarp
PathHopConfig(); PathHopConfig();
}; };
enum PathStatus
{
ePathBuilding,
ePathEstablished,
ePathTimeout,
ePathExpired
};
/// A path we made
struct Path struct Path
{ {
typedef std::vector< PathHopConfig > HopList; typedef std::vector< PathHopConfig > HopList;
HopList hops; HopList hops;
llarp_time_t buildStarted; llarp_time_t buildStarted;
PathStatus status;
Path(llarp_path_hops* path); Path(llarp_path_hops* path);
void
EncryptAndSend(llarp_buffer_t buf, llarp_router* r);
void
DecryptAndRecv(llarp_buffer_t buf, IEndpointHandler* handler);
const PathID_t&
PathID() const;
RouterID
Upstream();
}; };
template < typename User > template < typename User >
@ -132,32 +166,32 @@ namespace llarp
llarp_threadpool* worker = nullptr; llarp_threadpool* worker = nullptr;
llarp_logic* logic = nullptr; llarp_logic* logic = nullptr;
llarp_crypto* crypto = nullptr; llarp_crypto* crypto = nullptr;
LR_CommitMessage LRCM; LR_CommitMessage* LRCM = nullptr;
static void static void
HandleDone(void* user) HandleDone(void* u)
{ {
AsyncPathKeyExchangeContext< User >* ctx = AsyncPathKeyExchangeContext< User >* ctx =
static_cast< AsyncPathKeyExchangeContext< User >* >(user); static_cast< AsyncPathKeyExchangeContext< User >* >(u);
ctx->result(ctx); ctx->result(ctx);
delete ctx;
} }
static void static void
GenerateNextKey(void* user) GenerateNextKey(void* u)
{ {
AsyncPathKeyExchangeContext< User >* ctx = AsyncPathKeyExchangeContext< User >* ctx =
static_cast< AsyncPathKeyExchangeContext< User >* >(user); static_cast< AsyncPathKeyExchangeContext< User >* >(u);
auto& hop = ctx->path->hops[ctx->idx]; auto& hop = ctx->path->hops[ctx->idx];
// generate key // generate key
ctx->crypto->encryption_keygen(hop.commkey); ctx->crypto->encryption_keygen(hop.commkey);
hop.nonce.Randomize();
// do key exchange // do key exchange
if(!ctx->crypto->dh_client(hop.shared, hop.router.enckey, hop.nonce, if(!ctx->crypto->dh_client(hop.shared, hop.router.enckey, hop.commkey,
hop.commkey)) hop.nonce))
{ {
llarp::Error("Failed to generate shared key for path build"); llarp::Error("Failed to generate shared key for path build");
delete ctx; abort();
return; return;
} }
// randomize hop's path id // randomize hop's path id
@ -165,7 +199,7 @@ namespace llarp
LR_CommitRecord record; LR_CommitRecord record;
auto& frame = ctx->LRCM.frames[ctx->idx]; auto& frame = ctx->LRCM->frames[ctx->idx];
++ctx->idx; ++ctx->idx;
if(ctx->idx < ctx->path->hops.size()) if(ctx->idx < ctx->path->hops.size())
{ {
@ -175,12 +209,23 @@ namespace llarp
{ {
hop.upstream = hop.router.pubkey; hop.upstream = hop.router.pubkey;
} }
auto buf = frame.Buffer();
buf->cur = buf->base + EncryptedFrame::OverheadSize;
// generate record // generate record
if(!record.BEncode(frame.Buffer())) if(!record.BEncode(buf))
{ {
// failed to encode? // failed to encode?
llarp::Error("Failed to generate Commit Record"); llarp::Error("Failed to generate Commit Record");
delete ctx; abort();
return;
}
// rewind
buf->cur = buf->base;
if(!frame.EncryptInPlace(hop.commkey, hop.router.enckey, ctx->crypto))
{
llarp::Error("Failed to encrypt LRCR");
abort();
return; return;
} }
@ -210,11 +255,12 @@ namespace llarp
user = u; user = u;
result = func; result = func;
worker = pool; worker = pool;
LRCM = new LR_CommitMessage;
for(size_t idx = 0; idx < MAXHOPS; ++idx) for(size_t idx = 0; idx < MAXHOPS; ++idx)
{ {
LRCM.frames.emplace_back(256); LRCM->frames.emplace_back(256);
LRCM.frames.back().Randomize(); LRCM->frames.back().Randomize();
} }
llarp_threadpool_queue_job(pool, {this, &GenerateNextKey}); llarp_threadpool_queue_job(pool, {this, &GenerateNextKey});
} }
@ -227,56 +273,6 @@ namespace llarp
ePathBuildReject ePathBuildReject
}; };
/// path selection algorithm
struct IPathSelectionAlgorithm
{
virtual ~IPathSelectionAlgorithm(){};
/// select full path given an empty hop list to end at target
virtual bool
SelectFullPathTo(Path::HopList& hops, const RouterID& target) = 0;
/// report to path builder the result of a path build
/// can be used to "improve" path building algoirthm in the
/// future
virtual void
ReportPathBuildStatus(const Path::HopList& hops, const RouterID& target,
PathBuildStatus status){};
};
class PathBuildJob
{
public:
PathBuildJob(llarp_router* router, IPathSelectionAlgorithm* selector);
~PathBuildJob();
void
Start();
private:
typedef AsyncPathKeyExchangeContext< PathBuildJob > KeyExchanger;
LR_CommitMessage*
BuildLRCM();
static void
KeysGenerated(KeyExchanger* ctx);
llarp_router* router;
IPathSelectionAlgorithm* m_HopSelector;
KeyExchanger m_KeyExchanger;
};
/// a pool of paths for a hidden service
struct PathPool
{
PathPool(llarp_router* router);
~PathPool();
/// build a new path to a router by identity key
PathBuildJob*
BuildNewPathTo(const RouterID& router);
};
struct PathContext struct PathContext
{ {
PathContext(llarp_router* router); PathContext(llarp_router* router);
@ -300,28 +296,30 @@ namespace llarp
bool bool
HandleRelayCommit(const LR_CommitMessage* msg); HandleRelayCommit(const LR_CommitMessage* msg);
bool
HandleRelayAck(const LR_AckMessage* msg);
void void
PutTransitHop(const TransitHop& hop); PutTransitHop(const TransitHop& hop);
bool bool
ForwardLRCM(const RouterID& nextHop, std::deque< EncryptedFrame >& frames); ForwardLRCM(const RouterID& nextHop, std::deque< EncryptedFrame >& frames);
void
ForwradLRUM(const PathID_t& id, const RouterID& from, llarp_buffer_t X,
const TunnelNonce& nonce);
void
ForwradLRDM(const PathID_t& id, const RouterID& from, llarp_buffer_t X,
const TunnelNonce& nonce);
bool bool
HopIsUs(const PubKey& k) const; HopIsUs(const PubKey& k) const;
void
AddOwnPath(Path* p);
typedef std::unordered_multimap< PathID_t, TransitHop, PathIDHash > typedef std::unordered_multimap< PathID_t, TransitHop, PathIDHash >
TransitHopsMap_t; TransitHopsMap_t;
typedef std::pair< std::mutex, TransitHopsMap_t > SyncTransitMap_t; typedef std::pair< std::mutex, TransitHopsMap_t > SyncTransitMap_t;
typedef std::map< PathID_t, Path* > OwnedPathsMap_t;
typedef std::pair< std::mutex, OwnedPathsMap_t > SyncOwnedPathsMap_t;
llarp_threadpool* llarp_threadpool*
Worker(); Worker();
@ -340,6 +338,7 @@ namespace llarp
private: private:
llarp_router* m_Router; llarp_router* m_Router;
SyncTransitMap_t m_TransitPaths; SyncTransitMap_t m_TransitPaths;
SyncOwnedPathsMap_t m_OurPaths;
bool m_AllowTransit; bool m_AllowTransit;
}; };

@ -1,11 +1,12 @@
#ifndef LLARP_PATH_TYPES_HPP #ifndef LLARP_PATH_TYPES_HPP
#define LLARP_PATH_TYPES_HPP #define LLARP_PATH_TYPES_HPP
#include <llarp/crypto.h>
#include <llarp/aligned.hpp> #include <llarp/aligned.hpp>
namespace llarp namespace llarp
{ {
typedef AlignedBuffer< 16 > PathID_t; typedef AlignedBuffer< PATHIDSIZE > PathID_t;
} }
#endif #endif

@ -34,8 +34,10 @@ struct llarp_pathbuild_job;
/// response callback /// response callback
typedef void (*llarp_pathbuilder_hook)(struct llarp_pathbuild_job*); typedef void (*llarp_pathbuilder_hook)(struct llarp_pathbuild_job*);
// select hop function (nodedb, result, hopnnumber) called in logic thread // select hop function (nodedb, prevhop, result, hopnnumber) called in logic
// thread
typedef void (*llarp_pathbuilder_select_hop_func)(struct llarp_nodedb*, typedef void (*llarp_pathbuilder_select_hop_func)(struct llarp_nodedb*,
struct llarp_rc*,
struct llarp_rc*, size_t); struct llarp_rc*, size_t);
// request struct // request struct
@ -49,10 +51,8 @@ struct llarp_pathbuild_job
struct llarp_pathbuilder_context* context; struct llarp_pathbuilder_context* context;
// path hop selection // path hop selection
llarp_pathbuilder_select_hop_func selectHop; llarp_pathbuilder_select_hop_func selectHop;
// result handler // called when the path build started
llarp_pathbuilder_hook result; llarp_pathbuilder_hook pathBuildStarted;
// encryption secret key for hidden service
byte_t* secretkey;
// path // path
struct llarp_path_hops hops; struct llarp_path_hops hops;
}; };

@ -27,10 +27,8 @@ namespace iwp
{ {
iwp_async_keygen *keygen = static_cast< iwp_async_keygen * >(user); iwp_async_keygen *keygen = static_cast< iwp_async_keygen * >(user);
keygen->iwp->crypto->encryption_keygen(keygen->keybuf); keygen->iwp->crypto->encryption_keygen(keygen->keybuf);
llarp_thread_job job; keygen->hook(keygen);
job.user = user; // llarp_logic_queue_job(keygen->iwp->logic, job);
job.work = &inform_keygen;
llarp_logic_queue_job(keygen->iwp->logic, job);
} }
void void
@ -71,7 +69,8 @@ namespace iwp
buf.sz = intro->sz - 32; buf.sz = intro->sz - 32;
crypto->hmac(intro->buf, buf, sharedkey); crypto->hmac(intro->buf, buf, sharedkey);
// inform result // inform result
llarp_logic_queue_job(intro->iwp->logic, {intro, &inform_intro}); intro->hook(intro);
// llarp_logic_queue_job(intro->iwp->logic, {intro, &inform_intro});
} }
void void
@ -128,7 +127,7 @@ namespace iwp
{ {
iwp_async_introack *introack = static_cast< iwp_async_introack * >(user); iwp_async_introack *introack = static_cast< iwp_async_introack * >(user);
auto crypto = introack->iwp->crypto; auto crypto = introack->iwp->crypto;
auto logic = introack->iwp->logic; // auto logic = introack->iwp->logic;
llarp::ShortHash digest; llarp::ShortHash digest;
llarp::SharedSecret sharedkey; llarp::SharedSecret sharedkey;
@ -165,7 +164,8 @@ namespace iwp
// copy token // copy token
memcpy(introack->token, token, 32); memcpy(introack->token, token, 32);
} }
llarp_logic_queue_job(logic, {introack, &inform_introack}); introack->hook(introack);
// llarp_logic_queue_job(logic, {introack, &inform_introack});
} }
void void
@ -193,8 +193,9 @@ namespace iwp
buf.sz = introack->sz - 32; buf.sz = introack->sz - 32;
buf.cur = buf.base; buf.cur = buf.base;
crypto->hmac(introack->buf, buf, sharedkey); crypto->hmac(introack->buf, buf, sharedkey);
introack->hook(introack);
llarp_logic_queue_job(introack->iwp->logic, {introack, &inform_introack}); // llarp_logic_queue_job(introack->iwp->logic, {introack,
// &inform_introack});
} }
void void
@ -217,7 +218,7 @@ namespace iwp
auto hmac = crypto->hmac; auto hmac = crypto->hmac;
auto encrypt = crypto->xchacha20; auto encrypt = crypto->xchacha20;
auto logic = session->iwp->logic; // auto logic = session->iwp->logic;
auto a_sK = session->secretkey; auto a_sK = session->secretkey;
auto b_K = session->remote_pubkey; auto b_K = session->remote_pubkey;
auto N = session->nonce; auto N = session->nonce;
@ -251,8 +252,8 @@ namespace iwp
buf.base = (session->buf + 32); buf.base = (session->buf + 32);
buf.sz = session->sz - 32; buf.sz = session->sz - 32;
hmac(session->buf, buf, e_K); hmac(session->buf, buf, e_K);
session->hook(session);
llarp_logic_queue_job(logic, {user, &inform_session_start}); // llarp_logic_queue_job(logic, {user, &inform_session_start});
} }
void void
@ -267,7 +268,7 @@ namespace iwp
auto hmac = crypto->hmac; auto hmac = crypto->hmac;
auto decrypt = crypto->xchacha20; auto decrypt = crypto->xchacha20;
auto logic = session->iwp->logic; // auto logic = session->iwp->logic;
auto b_sK = session->secretkey; auto b_sK = session->secretkey;
auto a_K = session->remote_pubkey; auto a_K = session->remote_pubkey;
auto N = session->nonce; auto N = session->nonce;
@ -316,8 +317,8 @@ namespace iwp
} }
else // hmac fail else // hmac fail
session->buf = nullptr; session->buf = nullptr;
session->hook(session);
llarp_logic_queue_job(logic, {user, &inform_session_start}); // llarp_logic_queue_job(logic, {user, &inform_session_start});
} }
void void
@ -353,6 +354,9 @@ namespace iwp
buf.cur = buf.base; buf.cur = buf.base;
buf.sz = frame->sz - 64; buf.sz = frame->sz - 64;
crypto->xchacha20(buf, frame->sessionkey, nonce); crypto->xchacha20(buf, frame->sessionkey, nonce);
// call result RIGHT HERE
// frame->hook(frame);
// delete frame;
// inform result // inform result
llarp_logic_queue_job(frame->iwp->logic, {frame, &inform_frame_done}); llarp_logic_queue_job(frame->iwp->logic, {frame, &inform_frame_done});
} }

@ -16,14 +16,14 @@ namespace llarp
} }
static bool static bool
dh(uint8_t *out, uint8_t *client_pk, uint8_t *server_pk, uint8_t *pubkey, dh(uint8_t *out, uint8_t *client_pk, uint8_t *server_pk, uint8_t *themPub,
uint8_t *secret) uint8_t *usSec)
{ {
llarp::SharedSecret shared; llarp::SharedSecret shared;
crypto_generichash_state h; crypto_generichash_state h;
const size_t outsz = SHAREDKEYSIZE; const size_t outsz = SHAREDKEYSIZE;
if(crypto_scalarmult_curve25519(shared, secret, pubkey)) if(crypto_scalarmult_curve25519(shared, usSec, themPub))
return false; return false;
crypto_generichash_init(&h, NULL, 0U, outsz); crypto_generichash_init(&h, NULL, 0U, outsz);
crypto_generichash_update(&h, client_pk, 32); crypto_generichash_update(&h, client_pk, 32);
@ -34,31 +34,7 @@ namespace llarp
} }
static bool static bool
dh_client(byte_t *shared, byte_t *pk, byte_t *n, byte_t *sk) dh_client(uint8_t *shared, uint8_t *pk, uint8_t *sk, uint8_t *n)
{
if(dh(shared, llarp::seckey_topublic(sk), pk, pk, sk))
{
return crypto_generichash(shared, SHAREDKEYSIZE, shared, SHAREDKEYSIZE,
n, TUNNONCESIZE)
!= -1;
}
return false;
}
static bool
dh_server(byte_t *shared, byte_t *pk, byte_t *n, byte_t *sk)
{
if(dh(shared, pk, llarp::seckey_topublic(sk), pk, sk))
{
return crypto_generichash(shared, SHAREDKEYSIZE, shared, SHAREDKEYSIZE,
n, TUNNONCESIZE)
!= -1;
}
return false;
}
static bool
transport_dh_client(uint8_t *shared, uint8_t *pk, uint8_t *sk, uint8_t *n)
{ {
llarp::SharedSecret dh_result; llarp::SharedSecret dh_result;
if(dh(dh_result, llarp::seckey_topublic(sk), pk, pk, sk)) if(dh(dh_result, llarp::seckey_topublic(sk), pk, pk, sk))
@ -69,7 +45,7 @@ namespace llarp
} }
static bool static bool
transport_dh_server(uint8_t *shared, uint8_t *pk, uint8_t *sk, uint8_t *n) dh_server(uint8_t *shared, uint8_t *pk, uint8_t *sk, uint8_t *n)
{ {
llarp::SharedSecret dh_result; llarp::SharedSecret dh_result;
if(dh(dh_result, pk, llarp::seckey_topublic(sk), pk, sk)) if(dh(dh_result, pk, llarp::seckey_topublic(sk), pk, sk))
@ -156,7 +132,6 @@ namespace llarp
} // namespace llarp } // namespace llarp
extern "C" { extern "C" {
const byte_t * const byte_t *
llarp_seckey_topublic(const byte_t *secret) llarp_seckey_topublic(const byte_t *secret)
{ {
@ -170,8 +145,8 @@ llarp_crypto_libsodium_init(struct llarp_crypto *c)
c->xchacha20 = llarp::sodium::xchacha20; c->xchacha20 = llarp::sodium::xchacha20;
c->dh_client = llarp::sodium::dh_client; c->dh_client = llarp::sodium::dh_client;
c->dh_server = llarp::sodium::dh_server; c->dh_server = llarp::sodium::dh_server;
c->transport_dh_client = llarp::sodium::transport_dh_client; c->transport_dh_client = llarp::sodium::dh_client;
c->transport_dh_server = llarp::sodium::transport_dh_server; c->transport_dh_server = llarp::sodium::dh_server;
c->hash = llarp::sodium::hash; c->hash = llarp::sodium::hash;
c->shorthash = llarp::sodium::shorthash; c->shorthash = llarp::sodium::shorthash;
c->hmac = llarp::sodium::hmac; c->hmac = llarp::sodium::hmac;

@ -5,29 +5,21 @@
namespace llarp namespace llarp
{ {
Encrypted::Encrypted(const byte_t* buf, size_t sz) Encrypted::Encrypted(const byte_t* buf, size_t sz) : _data(sz)
{ {
size = sz;
data = new byte_t[sz];
if(buf) if(buf)
memcpy(data, buf, sz); memcpy(data(), buf, sz);
else else
llarp::Zero(data, sz); llarp::Zero(data(), sz);
m_Buffer.base = data; m_Buffer.base = data();
m_Buffer.cur = data; m_Buffer.cur = data();
m_Buffer.sz = size; m_Buffer.sz = size();
} }
Encrypted::Encrypted(size_t sz) : Encrypted(nullptr, sz) Encrypted::Encrypted(size_t sz) : Encrypted(nullptr, sz)
{ {
} }
Encrypted::~Encrypted()
{
if(data)
delete[] data;
}
bool bool
EncryptedFrame::EncryptInPlace(byte_t* ourSecretKey, byte_t* otherPubkey, EncryptedFrame::EncryptInPlace(byte_t* ourSecretKey, byte_t* otherPubkey,
llarp_crypto* crypto) llarp_crypto* crypto)
@ -38,7 +30,7 @@ namespace llarp
// <32 bytes pubkey> // <32 bytes pubkey>
// <N bytes encrypted payload> // <N bytes encrypted payload>
// //
byte_t* hash = data; byte_t* hash = data();
byte_t* nonce = hash + SHORTHASHSIZE; byte_t* nonce = hash + SHORTHASHSIZE;
byte_t* pubkey = nonce + TUNNONCESIZE; byte_t* pubkey = nonce + TUNNONCESIZE;
byte_t* body = pubkey + PUBKEYSIZE; byte_t* body = pubkey + PUBKEYSIZE;
@ -52,7 +44,7 @@ namespace llarp
llarp_buffer_t buf; llarp_buffer_t buf;
buf.base = body; buf.base = body;
buf.cur = buf.base; buf.cur = buf.base;
buf.sz = size - EncryptedFrame::OverheadSize; buf.sz = size() - EncryptedFrame::OverheadSize;
// set our pubkey // set our pubkey
memcpy(pubkey, llarp::seckey_topublic(ourSecretKey), PUBKEYSIZE); memcpy(pubkey, llarp::seckey_topublic(ourSecretKey), PUBKEYSIZE);
@ -60,11 +52,12 @@ namespace llarp
crypto->randbytes(nonce, TUNNONCESIZE); crypto->randbytes(nonce, TUNNONCESIZE);
// derive shared key // derive shared key
if(!DH(shared, otherPubkey, nonce, ourSecretKey)) if(!DH(shared, otherPubkey, ourSecretKey, nonce))
{ {
llarp::Error("DH failed"); llarp::Error("DH failed");
return false; return false;
} }
// encrypt body // encrypt body
if(!Encrypt(buf, shared, nonce)) if(!Encrypt(buf, shared, nonce))
{ {
@ -75,7 +68,7 @@ namespace llarp
// generate message auth // generate message auth
buf.base = nonce; buf.base = nonce;
buf.cur = buf.base; buf.cur = buf.base;
buf.sz = size - SHORTHASHSIZE; buf.sz = size() - SHORTHASHSIZE;
if(!MDS(hash, buf, shared)) if(!MDS(hash, buf, shared))
{ {
@ -88,9 +81,9 @@ namespace llarp
bool bool
EncryptedFrame::DecryptInPlace(byte_t* ourSecretKey, llarp_crypto* crypto) EncryptedFrame::DecryptInPlace(byte_t* ourSecretKey, llarp_crypto* crypto)
{ {
if(size <= size_t(EncryptedFrame::OverheadSize)) if(size() <= size_t(EncryptedFrame::OverheadSize))
{ {
llarp::Warn("encrypted frame too small, ", size, llarp::Warn("encrypted frame too small, ", size(),
" <= ", size_t(EncryptedFrame::OverheadSize)); " <= ", size_t(EncryptedFrame::OverheadSize));
return false; return false;
} }
@ -100,7 +93,7 @@ namespace llarp
// <32 bytes pubkey> // <32 bytes pubkey>
// <N bytes encrypted payload> // <N bytes encrypted payload>
// //
byte_t* hash = data; byte_t* hash = data();
byte_t* nonce = hash + SHORTHASHSIZE; byte_t* nonce = hash + SHORTHASHSIZE;
byte_t* otherPubkey = nonce + TUNNONCESIZE; byte_t* otherPubkey = nonce + TUNNONCESIZE;
byte_t* body = otherPubkey + PUBKEYSIZE; byte_t* body = otherPubkey + PUBKEYSIZE;
@ -113,12 +106,12 @@ namespace llarp
llarp_buffer_t buf; llarp_buffer_t buf;
buf.base = nonce; buf.base = nonce;
buf.cur = buf.base; buf.cur = buf.base;
buf.sz = size - SHORTHASHSIZE; buf.sz = size() - SHORTHASHSIZE;
SharedSecret shared; SharedSecret shared;
ShortHash digest; ShortHash digest;
if(!DH(shared, otherPubkey, nonce, ourSecretKey)) if(!DH(shared, otherPubkey, ourSecretKey, nonce))
{ {
llarp::Error("DH failed"); llarp::Error("DH failed");
return false; return false;
@ -138,7 +131,7 @@ namespace llarp
buf.base = body; buf.base = body;
buf.cur = body; buf.cur = body;
buf.sz = size - EncryptedFrame::OverheadSize; buf.sz = size() - EncryptedFrame::OverheadSize;
if(!Decrypt(buf, shared, nonce)) if(!Decrypt(buf, shared, nonce))
{ {

@ -30,8 +30,8 @@
namespace iwp namespace iwp
{ {
// session activity timeout is 5s // session activity timeout is 10s
constexpr llarp_time_t SESSION_TIMEOUT = 5000; constexpr llarp_time_t SESSION_TIMEOUT = 10000;
constexpr size_t MAX_PAD = 128; constexpr size_t MAX_PAD = 128;
@ -591,7 +591,7 @@ namespace iwp
void void
queue_tx(uint64_t id, transit_message *msg) queue_tx(uint64_t id, transit_message *msg)
{ {
tx[id] = msg; tx.insert(std::make_pair(id, msg));
msg->generate_xmit(sendqueue, txflags); msg->generate_xmit(sendqueue, txflags);
} }
@ -678,7 +678,7 @@ namespace iwp
uint32_t establish_job_id = 0; uint32_t establish_job_id = 0;
uint32_t frames = 0; uint32_t frames = 0;
bool working = false;
llarp::Addr addr; llarp::Addr addr;
iwp_async_intro intro; iwp_async_intro intro;
iwp_async_introack introack; iwp_async_introack introack;
@ -853,6 +853,8 @@ namespace iwp
// when we are done doing stuff with all of our frames from the crypto // when we are done doing stuff with all of our frames from the crypto
// workers we are done // workers we are done
llarp::Debug(addr, " timed out with ", frames, " frames left"); llarp::Debug(addr, " timed out with ", frames, " frames left");
if(working)
return false;
return frames == 0; return frames == 0;
} }
if(is_invalidated()) if(is_invalidated())
@ -862,12 +864,17 @@ namespace iwp
// are done // are done
llarp::Debug(addr, " invaldiated session with ", frames, llarp::Debug(addr, " invaldiated session with ", frames,
" frames left"); " frames left");
if(working)
return false;
return frames == 0; return frames == 0;
} }
// send keepalive if we are established or a session is made // send keepalive if we are established or a session is made
if(state == eEstablished || state == eLIMSent) if(state == eEstablished || state == eLIMSent)
{
send_keepalive(this); send_keepalive(this);
// pump frames
if(state == eEstablished)
{
frame.retransmit(); frame.retransmit();
pump(); pump();
} }
@ -905,6 +912,7 @@ namespace iwp
start.sessionkey = sessionkey; start.sessionkey = sessionkey;
start.user = this; start.user = this;
start.hook = &handle_verify_session_start; start.hook = &handle_verify_session_start;
working = true;
iwp_call_async_verify_session_start(iwp, &start); iwp_call_async_verify_session_start(iwp, &start);
} }
@ -954,6 +962,7 @@ namespace iwp
handle_generated_session_start(iwp_async_session_start *start) handle_generated_session_start(iwp_async_session_start *start)
{ {
session *link = static_cast< session * >(start->user); session *link = static_cast< session * >(start->user);
link->working = false;
if(llarp_ev_udp_sendto(link->udp, link->addr, start->buf, start->sz) if(llarp_ev_udp_sendto(link->udp, link->addr, start->buf, start->sz)
== -1) == -1)
llarp::Error("sendto failed"); llarp::Error("sendto failed");
@ -983,6 +992,7 @@ namespace iwp
start.sessionkey = sessionkey; start.sessionkey = sessionkey;
start.user = this; start.user = this;
start.hook = &handle_generated_session_start; start.hook = &handle_generated_session_start;
working = true;
iwp_call_async_gen_session_start(iwp, &start); iwp_call_async_gen_session_start(iwp, &start);
} }
@ -1090,6 +1100,7 @@ namespace iwp
// call // call
introack.user = this; introack.user = this;
introack.hook = &handle_introack_generated; introack.hook = &handle_introack_generated;
working = true;
iwp_call_async_gen_introack(iwp, &introack); iwp_call_async_gen_introack(iwp, &introack);
} }
@ -1100,7 +1111,7 @@ namespace iwp
{ {
// too big? // too big?
llarp::Error("intro too big"); llarp::Error("intro too big");
// TOOD: session destroy ? delete this;
return; return;
} }
// copy so we own it // copy so we own it
@ -1119,33 +1130,12 @@ namespace iwp
// call // call
EnterState(eIntroRecv); EnterState(eIntroRecv);
working = true;
iwp_call_async_verify_intro(iwp, &intro); iwp_call_async_verify_intro(iwp, &intro);
} }
void void
on_intro_ack(const void *buf, size_t sz) on_intro_ack(const void *buf, size_t sz);
{
if(sz >= sizeof(workbuf))
{
// too big?
llarp::Error("introack too big");
// TOOD: session destroy ?
return;
}
// copy buffer so we own it
memcpy(workbuf, buf, sz);
// set intro ack parameters
introack.buf = workbuf;
introack.sz = sz;
introack.nonce = workbuf + 32;
introack.remote_pubkey = remote;
introack.token = token;
introack.secretkey = eph_seckey;
introack.user = this;
introack.hook = &handle_verify_introack;
// async verify
iwp_call_async_verify_introack(iwp, &introack);
}
static llarp_link * static llarp_link *
get_parent(llarp_link_session *s); get_parent(llarp_link_session *s);
@ -1154,6 +1144,7 @@ namespace iwp
handle_generated_intro(iwp_async_intro *i) handle_generated_intro(iwp_async_intro *i)
{ {
session *link = static_cast< session * >(i->user); session *link = static_cast< session * >(i->user);
link->working = false;
if(i->buf) if(i->buf)
{ {
llarp::Debug("send intro"); llarp::Debug("send intro");
@ -1195,6 +1186,7 @@ namespace iwp
// async generate intro packet // async generate intro packet
intro.user = this; intro.user = this;
intro.hook = &handle_generated_intro; intro.hook = &handle_generated_intro;
working = true;
iwp_call_async_gen_intro(iwp, &intro); iwp_call_async_gen_intro(iwp, &intro);
// start introduce timer // start introduce timer
establish_job_id = llarp_logic_call_later( establish_job_id = llarp_logic_call_later(
@ -1402,7 +1394,10 @@ namespace iwp
if(itr != m_sessions.end()) if(itr != m_sessions.end())
{ {
llarp::Debug("removing session ", addr); llarp::Debug("removing session ", addr);
UnmapAddr(addr);
session *s = static_cast< session * >(itr->second.impl); session *s = static_cast< session * >(itr->second.impl);
m_sessions.erase(itr);
s->done();
if(s->frames) if(s->frames)
{ {
llarp::Warn("session has ", s->frames, llarp::Warn("session has ", s->frames,
@ -1411,8 +1406,6 @@ namespace iwp
} }
else else
delete s; delete s;
m_sessions.erase(itr);
UnmapAddr(addr);
} }
} }
@ -1479,7 +1472,6 @@ namespace iwp
{ {
// new inbound session // new inbound session
s = link->create_session(*saddr); s = link->create_session(*saddr);
llarp::Debug("new inbound session from ", s->addr);
} }
s->recv(buf, sz); s->recv(buf, sz);
} }
@ -1531,6 +1523,7 @@ namespace iwp
if(!impl->IsEstablished()) if(!impl->IsEstablished())
{ {
impl->send_LIM(); impl->send_LIM();
impl->session_established();
} }
} }
else else
@ -1552,16 +1545,18 @@ namespace iwp
delete rxmsg; delete rxmsg;
rx.erase(id); rx.erase(id);
return success; return success;
} } // namespace iwp
void void
session::handle_verify_intro(iwp_async_intro *intro) session::handle_verify_intro(iwp_async_intro *intro)
{ {
session *self = static_cast< session * >(intro->user); session *self = static_cast< session * >(intro->user);
self->working = false;
if(!intro->buf) if(!intro->buf)
{ {
llarp::Error("intro verify failed from ", self->addr, " via ", llarp::Error("intro verify failed from ", self->addr, " via ",
self->serv->addr); self->serv->addr);
delete self;
return; return;
} }
self->intro_ack(); self->intro_ack();
@ -1570,6 +1565,8 @@ namespace iwp
void void
session::session_established() session::session_established()
{ {
llarp::RouterID remote = remote_router.pubkey;
llarp::Info("session to ", remote, " established");
EnterState(eEstablished); EnterState(eEstablished);
serv->MapAddr(addr, remote_router.pubkey); serv->MapAddr(addr, remote_router.pubkey);
llarp_logic_cancel_call(logic, establish_job_id); llarp_logic_cancel_call(logic, establish_job_id);
@ -1578,6 +1575,37 @@ namespace iwp
void void
session::done() session::done()
{ {
if(establish_job_id)
{
llarp_logic_remove_call(logic, establish_job_id);
handle_establish_timeout(this, 0, 0);
}
}
void
session::on_intro_ack(const void *buf, size_t sz)
{
if(sz >= sizeof(workbuf))
{
// too big?
llarp::Error("introack too big");
serv->RemoveSessionByAddr(addr);
return;
}
// copy buffer so we own it
memcpy(workbuf, buf, sz);
// set intro ack parameters
introack.buf = workbuf;
introack.sz = sz;
introack.nonce = workbuf + 32;
introack.remote_pubkey = remote;
introack.token = token;
introack.secretkey = eph_seckey;
introack.user = this;
introack.hook = &handle_verify_introack;
// async verify
working = true;
iwp_call_async_verify_introack(iwp, &introack);
} }
void void
@ -1636,11 +1664,6 @@ namespace iwp
{ {
llarp::Debug("message transmitted msgid=", msgid); llarp::Debug("message transmitted msgid=", msgid);
session *impl = static_cast< session * >(parent->impl); session *impl = static_cast< session * >(parent->impl);
if(msgid == 0)
{
// first message acked means we are established
impl->session_established();
}
tx.erase(msgid); tx.erase(msgid);
delete msg; delete msg;
} }
@ -1664,10 +1687,12 @@ namespace iwp
session::handle_verify_introack(iwp_async_introack *introack) session::handle_verify_introack(iwp_async_introack *introack)
{ {
session *link = static_cast< session * >(introack->user); session *link = static_cast< session * >(introack->user);
link->working = false;
if(introack->buf == nullptr) if(introack->buf == nullptr)
{ {
// invalid signature // invalid signature
llarp::Error("introack verify failed from ", link->addr); llarp::Error("introack verify failed from ", link->addr);
// link->serv->RemoveSessionByAddr(link->addr);
return; return;
} }
link->EnterState(eIntroAckRecv); link->EnterState(eIntroAckRecv);
@ -1678,6 +1703,7 @@ namespace iwp
session::handle_verify_session_start(iwp_async_session_start *s) session::handle_verify_session_start(iwp_async_session_start *s)
{ {
session *self = static_cast< session * >(s->user); session *self = static_cast< session * >(s->user);
self->working = false;
if(!s->buf) if(!s->buf)
{ {
// verify fail // verify fail
@ -1871,14 +1897,15 @@ namespace iwp
void void
session::handle_establish_timeout(void *user, uint64_t orig, uint64_t left) session::handle_establish_timeout(void *user, uint64_t orig, uint64_t left)
{ {
if(orig == 0)
return;
session *self = static_cast< session * >(user); session *self = static_cast< session * >(user);
self->establish_job_id = 0; self->establish_job_id = 0;
if(self->establish_job) if(self->establish_job)
{ {
self->establish_job->link = self->serv->parent; self->establish_job->link = self->serv->parent;
if(left) if(self->IsEstablished())
{ {
// timer cancelled
self->establish_job->session = self->parent; self->establish_job->session = self->parent;
} }
else else
@ -1921,7 +1948,7 @@ namespace iwp
delete link; delete link;
} }
} }
} } // namespace iwp
extern "C" { extern "C" {
void void

@ -49,6 +49,7 @@ namespace llarp
return false; return false;
} }
// create the message to parse based off message type // create the message to parse based off message type
llarp::Debug("inbound message ", *strbuf.cur);
switch(*strbuf.cur) switch(*strbuf.cur)
{ {
case 'i': case 'i':
@ -113,4 +114,4 @@ namespace llarp
firstkey = true; firstkey = true;
return bencode_read_dict(&buf, &reader); return bencode_read_dict(&buf, &reader);
} }
} } // namespace llarp

@ -204,10 +204,14 @@ namespace llarp
std::size_t std::size_t
operator()(Addr const& a) const noexcept operator()(Addr const& a) const noexcept
{ {
if(a.af() == AF_INET)
{
return a.port() + a.addr4()->s_addr;
}
uint8_t empty[16] = {0}; uint8_t empty[16] = {0};
return (a.af() + memcmp(a.addr6(), empty, 16)) ^ a.port(); return (a.af() + memcmp(a.addr6(), empty, 16)) ^ a.port();
} }
}; };
} } // namespace llarp
#endif #endif

@ -292,7 +292,6 @@ nodedb_async_load_rc(void *user)
} }
extern "C" { extern "C" {
struct llarp_nodedb * struct llarp_nodedb *
llarp_nodedb_new(struct llarp_crypto *crypto) llarp_nodedb_new(struct llarp_crypto *crypto)
{ {
@ -352,7 +351,8 @@ llarp_nodedb_load_dir(struct llarp_nodedb *n, const char *dir)
void void
llarp_nodedb_async_verify(struct llarp_async_verify_rc *job) llarp_nodedb_async_verify(struct llarp_async_verify_rc *job)
{ {
// switch to crypto threadpool and continue with crypto_threadworker_verifyrc // switch to crypto threadpool and continue with
// crypto_threadworker_verifyrc
llarp_threadpool_queue_job(job->cryptoworker, llarp_threadpool_queue_job(job->cryptoworker,
{job, &crypto_threadworker_verifyrc}); {job, &crypto_threadworker_verifyrc});
} }
@ -373,4 +373,45 @@ llarp_nodedb_get_rc(struct llarp_nodedb *n, const byte_t *pk)
return nullptr; return nullptr;
} }
size_t
llarp_nodedb_num_loaded(struct llarp_nodedb *n)
{
return n->entries.size();
}
void
llarp_nodedb_select_random_hop(struct llarp_nodedb *n, struct llarp_rc *prev,
struct llarp_rc *result, size_t N)
{
/// TODO: check for "guard" status for N = 0?
auto sz = n->entries.size();
if(prev)
{
do
{
auto itr = n->entries.begin();
if(sz > 1)
{
auto idx = rand() % (sz - 1);
std::advance(itr, idx);
}
if(memcmp(prev->pubkey, itr->second.pubkey, PUBKEYSIZE) == 0)
continue;
llarp_rc_copy(result, &itr->second);
return;
} while(true);
}
else
{
auto itr = n->entries.begin();
if(sz > 1)
{
auto idx = rand() % (sz - 1);
std::advance(itr, idx);
}
llarp_rc_copy(result, &itr->second);
}
}
} // end extern } // end extern

@ -5,15 +5,6 @@
namespace llarp 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) PathContext::PathContext(llarp_router* router)
: m_Router(router), m_AllowTransit(false) : m_Router(router), m_AllowTransit(false)
{ {
@ -69,6 +60,7 @@ namespace llarp
PathContext::ForwardLRCM(const RouterID& nextHop, PathContext::ForwardLRCM(const RouterID& nextHop,
std::deque< EncryptedFrame >& frames) std::deque< EncryptedFrame >& frames)
{ {
llarp::Info("fowarding LRCM to ", nextHop);
LR_CommitMessage* msg = new LR_CommitMessage; LR_CommitMessage* msg = new LR_CommitMessage;
while(frames.size()) while(frames.size())
{ {
@ -101,6 +93,12 @@ namespace llarp
map.second.emplace(k, v); map.second.emplace(k, v);
} }
void
PathContext::AddOwnPath(Path* path)
{
MapPut(m_OurPaths, path->PathID(), path);
}
bool bool
PathContext::HasTransitHop(const TransitHopInfo& info) PathContext::HasTransitHop(const TransitHopInfo& info)
{ {
@ -148,4 +146,25 @@ namespace llarp
: pathID(record.pathid), upstream(record.nextHop), downstream(down) : pathID(record.pathid), upstream(record.nextHop), downstream(down)
{ {
} }
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);
}
}
const PathID_t&
Path::PathID() const
{
return hops[0].pathID;
}
RouterID
Path::Upstream()
{
return hops[0].router.pubkey;
}
} // namespace llarp } // namespace llarp

@ -20,18 +20,32 @@ namespace llarp
pathbuilder_generated_keys( pathbuilder_generated_keys(
AsyncPathKeyExchangeContext< llarp_pathbuild_job >* ctx) AsyncPathKeyExchangeContext< llarp_pathbuild_job >* ctx)
{ {
llarp::Debug("Generated keys for build"); auto remote = ctx->path->Upstream();
llarp::Debug("Generated LRCM to", remote);
auto router = ctx->user->router;
if(!router->SendToOrQueue(remote, ctx->LRCM))
{
llarp::Error("failed to send LRCM");
return;
}
ctx->path->status = ePathBuilding;
router->paths.AddOwnPath(ctx->path);
ctx->user->pathBuildStarted(ctx->user);
} }
void void
pathbuilder_start_build(void* user) pathbuilder_start_build(void* user)
{ {
// select hops
llarp_pathbuild_job* job = static_cast< llarp_pathbuild_job* >(user); llarp_pathbuild_job* job = static_cast< llarp_pathbuild_job* >(user);
size_t idx = 0; // select hops
size_t idx = 0;
llarp_rc* prev = nullptr;
while(idx < job->hops.numHops) while(idx < job->hops.numHops)
{ {
job->selectHop(job->router->nodedb, &job->hops.routers[idx], idx); llarp_rc* rc = &job->hops.hops[idx].router;
llarp_rc_clear(rc);
job->selectHop(job->router->nodedb, prev, rc, idx);
prev = rc;
++idx; ++idx;
} }
@ -42,21 +56,13 @@ namespace llarp
ctx->AsyncGenerateKeys(new Path(&job->hops), job->router->logic, ctx->AsyncGenerateKeys(new Path(&job->hops), job->router->logic,
job->router->tp, job, &pathbuilder_generated_keys); 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 } // namespace llarp
llarp_pathbuilder_context::llarp_pathbuilder_context( llarp_pathbuilder_context::llarp_pathbuilder_context(
llarp_router* p_router, struct llarp_dht_context* p_dht) llarp_router* p_router, struct llarp_dht_context* p_dht)
: router(p_router), dht(p_dht)
{ {
this->router = p_router;
this->dht = p_dht;
} }
extern "C" { extern "C" {
@ -82,6 +88,8 @@ llarp_pathbuilder_build_path(struct llarp_pathbuild_job* job)
return; return;
} }
job->router = job->context->router; job->router = job->context->router;
if(job->selectHop == nullptr)
job->selectHop = &llarp_nodedb_select_random_hop;
llarp_logic_queue_job(job->router->logic, llarp_logic_queue_job(job->router->logic,
{job, &llarp::pathbuilder_start_build}); {job, &llarp::pathbuilder_start_build});
} }

@ -75,6 +75,7 @@ namespace llarp
" when we are not allowing transit"); " when we are not allowing transit");
return false; return false;
} }
llarp::Info("Got LRCM from ", remote);
return AsyncDecrypt(&router->paths); return AsyncDecrypt(&router->paths);
} }
@ -237,7 +238,7 @@ namespace llarp
llarp::Info("Accepted ", self->hop.info); llarp::Info("Accepted ", self->hop.info);
self->context->PutTransitHop(self->hop); self->context->PutTransitHop(self->hop);
size_t sz = self->frames.front().size; size_t sz = self->frames.front().size();
// we pop the front element it was ours // we pop the front element it was ours
self->frames.pop_front(); self->frames.pop_front();
// put our response on the end // put our response on the end

@ -33,6 +33,7 @@ llarp_router::llarp_router()
, paths(this) , paths(this)
, dht(llarp_dht_context_new(this)) , dht(llarp_dht_context_new(this))
, inbound_msg_parser(this) , inbound_msg_parser(this)
, explorePool(llarp_pathbuilder_context_new(this, dht))
{ {
llarp_rc_clear(&rc); llarp_rc_clear(&rc);
@ -53,7 +54,7 @@ llarp_router::HandleRecvLinkMessage(llarp_link_session *session,
bool bool
llarp_router::SendToOrQueue(const llarp::RouterID &remote, llarp_router::SendToOrQueue(const llarp::RouterID &remote,
std::vector< llarp::ILinkMessage * > msgs) llarp::ILinkMessage *msg)
{ {
llarp_link *chosen = nullptr; llarp_link *chosen = nullptr;
if(!outboundLink->has_session_to(outboundLink, remote)) if(!outboundLink->has_session_to(outboundLink, remote))
@ -70,34 +71,38 @@ llarp_router::SendToOrQueue(const llarp::RouterID &remote,
else else
chosen = outboundLink; chosen = outboundLink;
for(const auto &msg : msgs) if(chosen)
{ {
// this will create an entry in the obmq if it's not already there SendTo(remote, msg, chosen);
outboundMesssageQueue[remote].push(msg); delete msg;
return true;
}
// this will create an entry in the obmq if it's not already there
auto itr = outboundMesssageQueue.find(remote);
if(itr == outboundMesssageQueue.end())
{
outboundMesssageQueue.emplace(std::make_pair(remote, MessageQueue()));
} }
outboundMesssageQueue[remote].push(msg);
if(!chosen) // we don't have an open session to that router right now
auto rc = llarp_nodedb_get_rc(nodedb, remote);
if(rc)
{ {
// we don't have an open session to that router right now // try connecting directly as the rc is loaded from disk
auto rc = llarp_nodedb_get_rc(nodedb, remote); llarp_router_try_connect(this, rc, 10);
if(rc) return true;
{
// try connecting directly as the rc is loaded from disk
llarp_router_try_connect(this, rc, 10);
return true;
}
// try requesting the rc from the disk
llarp_async_load_rc *job = new llarp_async_load_rc;
job->diskworker = disk;
job->nodedb = nodedb;
job->logic = logic;
job->user = this;
job->hook = &HandleAsyncLoadRCForSendTo;
memcpy(job->pubkey, remote, PUBKEYSIZE);
llarp_nodedb_async_load_rc(job);
} }
else // try requesting the rc from the disk
FlushOutboundFor(remote, chosen); llarp_async_load_rc *job = new llarp_async_load_rc;
job->diskworker = disk;
job->nodedb = nodedb;
job->logic = logic;
job->user = this;
job->hook = &HandleAsyncLoadRCForSendTo;
memcpy(job->pubkey, remote, PUBKEYSIZE);
llarp_nodedb_async_load_rc(job);
return true; return true;
} }
@ -281,10 +286,16 @@ llarp_router::connect_job_retry(void *user, uint64_t orig, uint64_t left)
return; return;
llarp_link_establish_job *job = llarp_link_establish_job *job =
static_cast< llarp_link_establish_job * >(user); static_cast< llarp_link_establish_job * >(user);
llarp::Addr remote = job->ai; llarp::Addr remote = job->ai;
llarp::Info("trying to establish session again with ", remote); if(job->link)
job->link->try_establish(job->link, job); {
llarp::Info("trying to establish session again with ", remote);
job->link->try_establish(job->link, job);
}
else
{
llarp::Error("establish session retry failed, no link for ", remote);
}
} }
void void
@ -359,13 +370,43 @@ llarp_router::handle_router_ticker(void *user, uint64_t orig, uint64_t left)
self->ScheduleTicker(orig); self->ScheduleTicker(orig);
} }
void
llarp_router::HandleExploritoryPathBuildStarted(llarp_pathbuild_job *job)
{
delete job;
}
void
llarp_router::BuildExploritoryPath()
{
llarp_pathbuild_job *job = new llarp_pathbuild_job;
job->context = explorePool;
job->selectHop = selectHopFunc;
job->hops.numHops = 4;
job->user = this;
job->pathBuildStarted = &HandleExploritoryPathBuildStarted;
llarp_pathbuilder_build_path(job);
}
void void
llarp_router::Tick() llarp_router::Tick()
{ {
llarp::Debug("tick router"); llarp::Debug("tick router");
paths.ExpirePaths(); paths.ExpirePaths();
llarp_pathbuild_job job; // TODO: don't do this if we have enough paths already
llarp_pathbuilder_build_path(&job); if(inboundLinks.size() == 0)
{
auto N = llarp_nodedb_num_loaded(nodedb);
if(N > 5)
{
BuildExploritoryPath();
}
else
{
llarp::Warn("not enough nodes known to build exploritory paths, have ", N,
" nodes");
}
}
llarp_link_session_iter iter; llarp_link_session_iter iter;
iter.user = this; iter.user = this;
iter.visit = &send_padded_message; iter.visit = &send_padded_message;
@ -401,7 +442,8 @@ llarp_router::send_padded_message(llarp_link_session_iter *itr,
} }
void void
llarp_router::SendTo(llarp::RouterID remote, llarp::ILinkMessage *msg) llarp_router::SendTo(llarp::RouterID remote, llarp::ILinkMessage *msg,
llarp_link *link)
{ {
llarp_buffer_t buf = llarp_buffer_t buf =
llarp::StackBuffer< decltype(linkmsg_buffer) >(linkmsg_buffer); llarp::StackBuffer< decltype(linkmsg_buffer) >(linkmsg_buffer);
@ -415,7 +457,11 @@ llarp_router::SendTo(llarp::RouterID remote, llarp::ILinkMessage *msg)
// set size of message // set size of message
buf.sz = buf.cur - buf.base; buf.sz = buf.cur - buf.base;
buf.cur = buf.base; buf.cur = buf.base;
if(link)
{
link->sendto(link, remote, buf);
return;
}
bool sent = outboundLink->sendto(outboundLink, remote, buf); bool sent = outboundLink->sendto(outboundLink, remote, buf);
if(!sent) if(!sent)
{ {
@ -456,7 +502,9 @@ llarp_router::FlushOutboundFor(const llarp::RouterID &remote,
llarp::Debug("Flush outbound for ", remote); llarp::Debug("Flush outbound for ", remote);
auto itr = outboundMesssageQueue.find(remote); auto itr = outboundMesssageQueue.find(remote);
if(itr == outboundMesssageQueue.end()) if(itr == outboundMesssageQueue.end())
{
return; return;
}
while(itr->second.size()) while(itr->second.size())
{ {
auto buf = llarp::StackBuffer< decltype(linkmsg_buffer) >(linkmsg_buffer); auto buf = llarp::StackBuffer< decltype(linkmsg_buffer) >(linkmsg_buffer);
@ -599,15 +647,21 @@ llarp_router::Run()
{ {
// initialize as service node // initialize as service node
InitServiceNode(); InitServiceNode();
// immediate connect all for service node
auto delay = rand() % 100;
llarp_logic_call_later(logic, {delay, this, &ConnectAll});
}
else
{ // delayed connect all for clients
auto delay = ((rand() % 10) * 500) + 1000;
llarp_logic_call_later(logic, {delay, this, &ConnectAll});
} }
llarp::PubKey ourPubkey = pubkey(); llarp::PubKey ourPubkey = pubkey();
llarp::Info("starting dht context as ", ourPubkey); llarp::Info("starting dht context as ", ourPubkey);
llarp_dht_context_start(dht, ourPubkey); llarp_dht_context_start(dht, ourPubkey);
llarp_logic_call_later(logic, {1000, this, &ConnectAll}); ScheduleTicker(1000);
ScheduleTicker(500);
} }
void void

@ -72,6 +72,7 @@ struct llarp_router
llarp::InboundMessageParser inbound_msg_parser; llarp::InboundMessageParser inbound_msg_parser;
llarp_pathbuilder_select_hop_func selectHopFunc = nullptr; llarp_pathbuilder_select_hop_func selectHopFunc = nullptr;
llarp_pathbuilder_context *explorePool = nullptr;
llarp_link *outboundLink = nullptr; llarp_link *outboundLink = nullptr;
std::list< llarp_link * > inboundLinks; std::list< llarp_link * > inboundLinks;
@ -79,15 +80,12 @@ struct llarp_router
typedef std::queue< llarp::ILinkMessage * > MessageQueue; typedef std::queue< llarp::ILinkMessage * > MessageQueue;
/// outbound message queue /// outbound message queue
std::unordered_map< llarp::PubKey, MessageQueue, llarp::PubKeyHash > std::map< llarp::PubKey, MessageQueue > outboundMesssageQueue;
outboundMesssageQueue;
/// loki verified routers /// loki verified routers
std::unordered_map< llarp::PubKey, llarp_rc, llarp::PubKeyHash > validRouters; std::unordered_map< llarp::PubKey, llarp_rc, llarp::PubKeyHash > validRouters;
std::unordered_map< llarp::PubKey, llarp_link_establish_job, std::map< llarp::PubKey, llarp_link_establish_job > pendingEstablishJobs;
llarp::PubKeyHash >
pendingEstablishJobs;
llarp_router(); llarp_router();
~llarp_router(); ~llarp_router();
@ -144,12 +142,12 @@ struct llarp_router
/// NOT threadsafe /// NOT threadsafe
/// MUST be called in the logic thread /// MUST be called in the logic thread
bool bool
SendToOrQueue(const llarp::RouterID &remote, SendToOrQueue(const llarp::RouterID &remote, llarp::ILinkMessage *msg);
std::vector< llarp::ILinkMessage * > msgs);
/// sendto or drop /// sendto or drop
void void
SendTo(llarp::RouterID remote, llarp::ILinkMessage *msg); SendTo(llarp::RouterID remote, llarp::ILinkMessage *msg,
llarp_link *chosen = nullptr);
/// manually flush outbound message queue for just 1 router /// manually flush outbound message queue for just 1 router
void void
@ -171,6 +169,9 @@ struct llarp_router
void void
Tick(); Tick();
void
BuildExploritoryPath();
/// schedule ticker to call i ms from now /// schedule ticker to call i ms from now
void void
ScheduleTicker(uint64_t i = 1000); ScheduleTicker(uint64_t i = 1000);
@ -207,6 +208,9 @@ struct llarp_router
static void static void
HandleDHTLookupForSendTo(llarp_router_lookup_job *job); HandleDHTLookupForSendTo(llarp_router_lookup_job *job);
static void
HandleExploritoryPathBuildStarted(llarp_pathbuild_job *job);
}; };
#endif #endif

@ -0,0 +1,57 @@
#include <gtest/gtest.h>
#include <llarp/crypto.hpp>
#include <llarp/encrypted_frame.hpp>
#include <llarp/messages/relay_commit.hpp>
using EncryptedFrame = llarp::EncryptedFrame;
using SecretKey = llarp::SecretKey;
using PubKey = llarp::PubKey;
using LRAR = llarp::LR_AcceptRecord;
class FrameTest : public ::testing::Test
{
public:
llarp_crypto crypto;
SecretKey alice, bob;
FrameTest()
{
llarp_crypto_libsodium_init(&crypto);
}
~FrameTest()
{
}
void
SetUp()
{
crypto.encryption_keygen(alice);
crypto.encryption_keygen(bob);
}
void
TearDown()
{
}
};
TEST_F(FrameTest, TestFrameCrypto)
{
EncryptedFrame f(256);
f.Fill(0);
LRAR record;
record.upstream.Fill(1);
record.downstream.Fill(2);
record.pathid.Fill(3);
auto buf = f.Buffer();
buf->cur = buf->base + EncryptedFrame::OverheadSize;
ASSERT_TRUE(record.BEncode(buf));
buf->cur = buf->base;
// encrypt alice to bob
ASSERT_TRUE(f.EncryptInPlace(alice, llarp::seckey_topublic(bob), &crypto));
ASSERT_TRUE(f.DecryptInPlace(bob, &crypto));
};
Loading…
Cancel
Save