more refactor

get rid of C api
pull/15/head
Jeff Becker 6 years ago
parent b122fc59f8
commit 5228a81bae
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -3,7 +3,7 @@
#include <signal.h>
#include "logger.hpp"
#include <llarp/router_contact.h>
#include <llarp/router_contact.hpp>
#include <llarp/time.h>
#include <fstream>

@ -4,8 +4,6 @@
#include <llarp/ev.h>
#include <llarp/logic.h>
#include <llarp/mem.h>
#include <llarp/nodedb.h>
#include <llarp/router.h>
#include <llarp/version.h>
#ifdef __cplusplus

@ -6,6 +6,7 @@
#include <llarp/threading.hpp>
#include <string>
#include <vector>
#include <llarp/crypto.h>
namespace llarp
{

@ -0,0 +1,36 @@
#ifndef LLARP_AI_HPP
#define LLARP_AI_HPP
#include <llarp/mem.h>
#include <llarp/net.h>
#include <stdbool.h>
#include <llarp/crypto.hpp>
#include <string>
/**
* address_info.hpp
*
* utilities for handling addresses on the llarp network
*/
/// address information model
namespace llarp
{
struct AddressInfo
{
uint16_t rank;
std::string dialect;
llarp::PubKey pubkey;
struct in6_addr ip;
uint16_t port;
bool
BEncode(llarp_buffer_t *buf) const;
bool
BDecode(llarp_buffer_t *buf);
};
} // namespace llarp
#endif

@ -38,6 +38,20 @@ namespace llarp
return bencode_write_bytestring(buf, k, 1) && bencode_write_uint64(buf, i);
}
template < typename List_t >
bool
BEncodeMaybeReadDictList(const char* k, List_t& item, bool& read,
llarp_buffer_t key, llarp_buffer_t* buf)
{
if(llarp_buffer_eq(key, k))
{
if(!BEncodeReadList(item, buf))
return false;
read = true;
}
return true;
}
template < typename Item_t >
bool
BEncodeMaybeReadDictEntry(const char* k, Item_t& item, bool& read,
@ -105,6 +119,43 @@ namespace llarp
return bencode_end(buf);
}
template < typename Array >
bool
BEncodeWriteDictArray(const char* k, const Array& array, llarp_buffer_t* buf)
{
if(!bencode_write_bytestring(buf, k, 1))
return false;
if(!bencode_start_list(buf))
return false;
for(size_t idx = 0; idx < array.size(); ++idx)
if(!array[idx].BEncode(buf))
return false;
return bencode_end(buf);
}
template < typename Array >
bool
BEncodeReadArray(Array& array, llarp_buffer_t* buf)
{
if(*buf->cur != 'l') // ensure is a list
return false;
buf->cur++;
size_t idx = 0;
while(llarp_buffer_size_left(*buf) && *buf->cur != 'e')
{
if(idx >= array.size())
return false;
if(!array[idx++].BDecode(buf))
return false;
}
if(*buf->cur != 'e') // make sure we're at a list end
return false;
buf->cur++;
return true;
}
template < typename Iter >
bool
BEncodeWriteList(Iter itr, Iter end, llarp_buffer_t* buf)
@ -212,4 +263,4 @@ namespace llarp
} // namespace llarp
#endif
#endif

@ -24,39 +24,13 @@ llarp_dht_context_free(struct llarp_dht_context* dht);
void
llarp_dht_context_start(struct llarp_dht_context* ctx, const byte_t* key);
struct llarp_router_lookup_job;
typedef void (*llarp_router_lookup_handler)(struct llarp_router_lookup_job*);
struct llarp_router_lookup_job
{
/// can be anything but usually a class context for hook
void* user;
llarp_router_lookup_handler hook;
struct llarp_dht_context* dht;
byte_t target[PUBKEYSIZE];
bool found;
// make sure you initialize addr and exits
struct llarp_rc result;
bool iterative;
};
/// start allowing dht participation on a context
void
llarp_dht_allow_transit(struct llarp_dht_context* ctx);
/// put router as a dht peer
/// internal function do not use
void
__llarp_dht_put_peer(struct llarp_dht_context* ctx, struct llarp_rc* rc);
/// remove router from tracked dht peer list
/// internal function do not use
void
__llarp_dht_remove_peer(struct llarp_dht_context* ctx, const byte_t* id);
void
llarp_dht_lookup_router(struct llarp_dht_context* ctx,
struct llarp_router_lookup_job* job);
#endif

@ -106,6 +106,9 @@ namespace llarp
typedef std::function< void(const std::vector< service::IntroSet >&) >
IntroSetLookupHandler;
typedef std::function< void(const std::vector< RouterContact >&) >
RouterLookupHandler;
struct Context
{
Context();
@ -130,7 +133,17 @@ namespace llarp
void
LookupRouterRecursive(const RouterID& target, const Key_t& whoasked,
uint64_t whoaskedTX, const Key_t& askpeer,
llarp_router_lookup_job* job = nullptr);
RouterLookupHandler result = nullptr);
bool
LookupRouter(const RouterID& target, RouterLookupHandler result)
{
Key_t askpeer;
if(!nodes->FindClosest(target.data(), askpeer))
return false;
LookupRouterRecursive(target, OurKey(), 0, askpeer, result);
return true;
}
/// on behalf of whoasked request introsets with tag from dht router with
/// key askpeer with Recursion depth R
@ -138,14 +151,16 @@ namespace llarp
LookupTagRecursive(const service::Tag& tag, const Key_t& whoasked,
uint64_t whoaskedTX, const Key_t& askpeer, uint64_t R);
void
LookupRouterViaJob(llarp_router_lookup_job* job);
/// issue dht lookup for tag via askpeer and send reply to local path
void
LookupTagForPath(const service::Tag& tag, uint64_t txid,
const llarp::PathID_t& path, const Key_t& askpeer);
/// issue dht lookup for router via askpeer and send reply to local path
void
LookupRouterForPath(const RouterID& target, uint64_t txid,
const llarp::PathID_t& path, const Key_t& askpeer);
/// issue dht lookup for introset for addr via askpeer and send reply to
/// local path
void
@ -193,10 +208,6 @@ namespace llarp
const llarp::service::IntroSet*
GetIntroSetByServiceAddress(const llarp::service::Address& addr) const;
/// queue lookup router via job
void
QueueRouterLookup(llarp_router_lookup_job* job);
static void
handle_cleaner_timer(void* user, uint64_t orig, uint64_t left);
@ -207,9 +218,6 @@ namespace llarp
void
Explore();
static void
queue_router_lookup(void* user);
llarp_router* router = nullptr;
// for router contacts
Bucket< RCNode >* nodes = nullptr;
@ -340,7 +348,7 @@ namespace llarp
TXHolder< service::Tag, service::IntroSet, service::Tag::Hash >
pendingTagLookups;
TXHolder< RouterID, llarp_rc, RouterID::Hash > pendingRouterLookups;
TXHolder< RouterID, RouterContact, RouterID::Hash > pendingRouterLookups;
TXHolder< RouterID, RouterID, RouterID::Hash > pendingExploreLookups;

@ -1,6 +1,7 @@
#ifndef LLARP_DHT_MESSAGES_GOT_ROUTER_HPP
#define LLARP_DHT_MESSAGES_GOT_ROUTER_HPP
#include <llarp/dht/message.hpp>
#include <llarp/router_contact.hpp>
namespace llarp
{
@ -12,16 +13,11 @@ namespace llarp
: IMessage(from), relayed(tunneled)
{
}
GotRouterMessage(const Key_t& from, uint64_t id, const llarp_rc* result,
GotRouterMessage(const Key_t& from, uint64_t id,
const std::vector< RouterContact >& results,
bool tunneled)
: IMessage(from), txid(id), relayed(tunneled)
: IMessage(from), R(results), txid(id), relayed(tunneled)
{
if(result)
{
R.emplace_back();
llarp_rc_clear(&R.back());
llarp_rc_copy(&R.back(), result);
}
}
GotRouterMessage(uint64_t id, const std::vector< RouterID >& near,
@ -42,7 +38,7 @@ namespace llarp
HandleMessage(llarp_dht_context* ctx,
std::vector< IMessage* >& replies) const;
std::vector< llarp_rc > R;
std::vector< RouterContact > R;
std::vector< RouterID > N;
uint64_t txid = 0;
uint64_t version = 0;

@ -1,7 +1,7 @@
#ifndef LLARP_DHT_NODE_HPP
#define LLARP_DHT_NODE_HPP
#include <llarp/router_contact.h>
#include <llarp/router_contact.hpp>
#include <llarp/dht/key.hpp>
#include <llarp/service/IntroSet.hpp>
@ -11,18 +11,19 @@ namespace llarp
{
struct RCNode
{
llarp_rc* rc;
llarp::RouterContact rc;
Key_t ID;
RCNode() : rc(nullptr)
RCNode()
{
ID.Zero();
}
RCNode(llarp_rc* other) : rc(other)
RCNode(const llarp::RouterContact& other)
{
ID = other->pubkey;
rc = other;
ID = other.pubkey.data();
}
};
@ -47,4 +48,4 @@ namespace llarp
} // namespace dht
} // namespace llarp
#endif
#endif

@ -5,12 +5,15 @@
#include <llarp/buffer.h>
#include <sodium.h>
#include <vector>
#include <stdexcept>
namespace llarp
{
/// encrypted buffer base type
struct Encrypted
{
static const size_t MAX_SIZE = (1024 * 8);
Encrypted(Encrypted&&) = delete;
Encrypted(const Encrypted& other);
Encrypted();
@ -31,15 +34,13 @@ namespace llarp
}
Encrypted&
operator=(llarp_buffer_t buf)
operator=(const llarp_buffer_t& buf)
{
if(_data)
delete[] _data;
_data = nullptr;
_sz = buf.sz;
if(buf.sz > MAX_SIZE)
return *this;
_sz = buf.sz;
if(_sz)
{
_data = new byte_t[_sz];
memcpy(_data, buf.base, _sz);
}
UpdateBuffer();
@ -69,10 +70,9 @@ namespace llarp
return false;
if(strbuf.sz == 0)
return false;
if(_data)
delete[] _data;
_sz = strbuf.sz;
_data = new byte_t[_sz];
if(strbuf.sz > MAX_SIZE)
return false;
_sz = strbuf.sz;
memcpy(_data, strbuf.base, _sz);
UpdateBuffer();
return true;
@ -116,10 +116,10 @@ namespace llarp
m_Buffer.cur = data();
m_Buffer.sz = size();
}
byte_t* _data = nullptr;
size_t _sz = 0;
byte_t _data[MAX_SIZE];
size_t _sz = 0;
llarp_buffer_t m_Buffer;
};
} // namespace llarp
#endif
#endif

@ -33,10 +33,9 @@ namespace llarp
EncryptedFrame&
operator=(const EncryptedFrame& other)
{
if(_data)
delete[] _data;
_sz = other._sz;
_data = new byte_t[_sz];
if(other._sz > MAX_SIZE)
throw std::logic_error("encrypted frame too big");
_sz = other._sz;
memcpy(_data, other._data, _sz);
return *this;
}

@ -0,0 +1,45 @@
#ifndef LLARP_XI_HPP
#define LLARP_XI_HPP
#include <llarp/buffer.h>
#include <llarp/crypto.hpp>
#include <llarp/net.h>
#include <iostream>
#include <llarp/bits.hpp>
/**
* exit_info.h
*
* utilities for handling exits on the llarp network
*/
/// Exit info model
namespace llarp
{
struct ExitInfo
{
struct in6_addr address;
struct in6_addr netmask;
PubKey pubkey;
bool
BEncode(llarp_buffer_t *buf) const;
bool
BDecode(llarp_buffer_t *buf);
friend std::ostream &
operator<<(std::ostream &out, const ExitInfo &xi)
{
char tmp[128] = {0};
if(inet_ntop(AF_INET6, &xi.address, tmp, sizeof(tmp)))
out << std::string(tmp);
else
return out;
out << std::string("/");
return out << std::to_string(
llarp::bits::count_array_bits(xi.netmask.s6_addr));
}
};
} // namespace llarp
#endif

@ -1,6 +1,6 @@
#pragma once
#include "llarp/address_info.h"
#include "llarp/address_info.hpp"
struct llarp_link;
struct llarp_link_session;
@ -9,13 +9,13 @@ struct llarp_link_establish_job
{
void *user;
void (*result)(struct llarp_link_establish_job *);
struct llarp_ai ai;
llarp::AddressInfo ai;
uint64_t timeout;
uint16_t retries;
byte_t pubkey[PUBKEYSIZE];
llarp::PubKey pubkey;
/** set on success by try_establish */
struct llarp_link *link;
/** set on success by try_establish */
struct llarp_link_session *session;
};
};

@ -86,7 +86,7 @@ struct frame_state
clear();
bool
inbound_frame_complete(uint64_t id);
inbound_frame_complete(const std::unique_ptr< transit_message > &msg);
void
push_ackfor(uint64_t id, uint32_t bitmask);

@ -9,12 +9,26 @@
struct InboundMessage
{
uint64_t msgid;
std::vector< byte_t > msg;
byte_t *_buf;
size_t sz;
llarp_time_t queued = 0;
InboundMessage(uint64_t id, const std::vector< byte_t > &m)
: msgid(id), msg(m)
InboundMessage(uint64_t id, const std::vector< byte_t > &m) : msgid(id)
{
sz = m.size();
if(sz)
{
_buf = new byte_t[sz];
memcpy(_buf, m.data(), sz);
}
else
_buf = nullptr;
}
~InboundMessage()
{
if(_buf)
delete[] _buf;
}
bool
@ -27,7 +41,7 @@ struct InboundMessage
llarp_buffer_t
Buffer() const
{
return llarp::ConstBuffer< decltype(msg) >(msg);
return llarp::InitBuffer(_buf, sz);
}
struct GetTime

@ -7,25 +7,35 @@
struct sendbuf_t
{
sendbuf_t(size_t s) : sz(s)
sendbuf_t()
{
_buf = new byte_t[s];
_sz = 0;
}
~sendbuf_t()
sendbuf_t(sendbuf_t &&other)
{
if(_buf)
delete[] _buf;
if(other._sz > sizeof(_buf))
throw std::logic_error("sendbuf too big");
memcpy(_buf, other._buf, other._sz);
_sz = other._sz;
other._sz = 0;
}
size_t sz;
sendbuf_t(size_t s)
{
if(s > sizeof(_buf))
throw std::logic_error("sendbuf too big");
_sz = s;
}
byte_t priority = 255;
~sendbuf_t()
{
}
size_t
size() const
{
return sz;
return _sz;
}
byte_t *
@ -39,7 +49,7 @@ struct sendbuf_t
{
llarp_buffer_t buf;
buf.base = _buf;
buf.sz = sz;
buf.sz = _sz;
buf.cur = buf.base;
return buf;
}
@ -74,5 +84,6 @@ struct sendbuf_t
llarp_time_t timestamp = 0;
private:
byte_t *_buf = nullptr;
size_t _sz;
byte_t _buf[1500];
};

@ -139,7 +139,7 @@ struct llarp_link
issue_cleanup_timer(uint64_t timeout);
void
get_our_address(struct llarp_ai *addr);
get_our_address(llarp::AddressInfo &addr);
static void
after_recv(llarp_udp_io *udp);

@ -7,7 +7,7 @@
#include "llarp/crypto.hpp"
#include "llarp/crypto_async.h"
#include "llarp/net.hpp"
#include "llarp/router_contact.h"
#include "llarp/router_contact.hpp"
#include "llarp/time.h"
#include "llarp/types.h"
@ -47,8 +47,9 @@ struct llarp_link_session
llarp_link *
get_parent();
llarp_rc *
get_remote_router();
const llarp::RouterContact &
get_remote_router() const;
bool
CheckRCValid();
@ -110,8 +111,8 @@ struct llarp_link_session
llarp_link *serv = nullptr;
llarp_rc *our_router = nullptr;
llarp_rc remote_router;
llarp::RouterContact *our_router = nullptr;
llarp::RouterContact remote_router;
llarp::SecretKey eph_seckey;
llarp::PubKey remote;

@ -5,13 +5,17 @@ namespace llarp
{
struct LinkIntroMessage : public ILinkMessage
{
LinkIntroMessage(llarp_rc* rc) : ILinkMessage(), RC(rc)
LinkIntroMessage(const RouterContact& rc) : ILinkMessage(), RC(rc)
{
hasRC = true;
}
LinkIntroMessage();
~LinkIntroMessage();
llarp_rc* RC;
bool hasRC = false;
RouterContact RC;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf);

@ -45,7 +45,7 @@ namespace llarp
struct LR_CommitMessage : public ILinkMessage
{
std::vector< EncryptedFrame > frames;
std::array< EncryptedFrame, 8 > frames;
uint64_t version;
LR_CommitMessage() : ILinkMessage()

@ -1,6 +1,6 @@
#ifndef LLARP_NET_HPP
#define LLARP_NET_HPP
#include <llarp/address_info.h>
#include <llarp/address_info.hpp>
#include <llarp/net.h>
#include <functional>
#include <iostream>
@ -55,7 +55,7 @@ namespace llarp
return (const in_addr*)&_addr.sin6_addr.s6_addr[12];
}
Addr(const llarp_ai& other)
Addr(const AddressInfo& other)
{
memcpy(addr6(), other.ip.s6_addr, 16);
_addr.sin6_port = htons(other.port);

@ -1,11 +1,12 @@
#ifndef LLARP_NODEDB_H
#define LLARP_NODEDB_H
#ifndef LLARP_NODEDB_HPP
#define LLARP_NODEDB_HPP
#include <llarp/common.h>
#include <llarp/crypto.h>
#include <llarp/router_contact.h>
#include <llarp/router_contact.hpp>
#include <llarp/router_id.hpp>
/**
* nodedb.h
* nodedb.hpp
*
* persistent storage API for router contacts
*/
@ -39,7 +40,7 @@ llarp_nodedb_store_dir(struct llarp_nodedb *n, const char *dir);
struct llarp_nodedb_iter
{
void *user;
struct llarp_rc *rc;
llarp::RouterContact *rc;
size_t index;
bool (*visit)(struct llarp_nodedb_iter *);
};
@ -48,15 +49,6 @@ struct llarp_nodedb_iter
int
llarp_nodedb_iterate_all(struct llarp_nodedb *n, struct llarp_nodedb_iter i);
/// get a random rc that is loaded
void
llarp_nodedb_get_random_rc(struct llarp_nodedb *n, struct llarp_rc *result);
/// select a random rc at hop number N
void
llarp_nodedb_select_random_hop(struct llarp_nodedb *n, struct llarp_rc *prev,
struct llarp_rc *result, size_t N);
/// return number of RC loaded
size_t
llarp_nodedb_num_loaded(struct llarp_nodedb *n);
@ -68,11 +60,11 @@ llarp_nodedb_num_loaded(struct llarp_nodedb *n);
returns true on success and false on error
*/
bool
llarp_nodedb_put_rc(struct llarp_nodedb *n, struct llarp_rc *rc);
llarp_nodedb_put_rc(struct llarp_nodedb *n, const llarp::RouterContact &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);
bool
llarp_nodedb_get_rc(struct llarp_nodedb *n, const llarp::RouterID &pk,
llarp::RouterContact &result);
/// struct for async rc verification
struct llarp_async_verify_rc;
@ -94,7 +86,7 @@ struct llarp_async_verify_rc
struct llarp_threadpool *diskworker;
/// router contact
struct llarp_rc rc;
llarp::RouterContact rc;
/// result
bool valid;
/// hook
@ -125,9 +117,9 @@ struct llarp_async_load_rc
/// disk worker threadpool
struct llarp_threadpool *diskworker;
/// target pubkey
byte_t pubkey[PUBKEYSIZE];
llarp::PubKey pubkey;
/// router contact result
struct llarp_rc rc;
llarp::RouterContact result;
/// set to true if we loaded the rc
bool loaded;
/// hook function called in logic thread
@ -138,4 +130,9 @@ struct llarp_async_load_rc
void
llarp_nodedb_async_load_rc(struct llarp_async_load_rc *job);
void
llarp_nodedb_select_random_hop(struct llarp_nodedb *n,
const llarp::RouterContact &prev,
llarp::RouterContact &result, size_t N);
#endif

@ -1,28 +0,0 @@
#ifndef LLARP_PATH_H
#define LLARP_PATH_H
#include <llarp/router_contact.h>
#define MAXHOPS (8)
#define DEFAULT_PATH_LIFETIME (10 * 60 * 1000)
#define PATH_BUILD_TIMEOUT (10 * 1000)
#define MESSAGE_PAD_SIZE (1024)
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_hop hops[MAXHOPS];
size_t numHops;
};
void
llarp_path_hops_free(struct llarp_path_hops* hops);
#endif

@ -1,6 +1,5 @@
#ifndef LLARP_PATH_HPP
#define LLARP_PATH_HPP
#include <llarp/path.h>
#include <llarp/router.h>
#include <llarp/time.h>
#include <llarp/aligned.hpp>
@ -10,6 +9,7 @@
#include <llarp/messages/relay_commit.hpp>
#include <llarp/path_types.hpp>
#include <llarp/pathset.hpp>
#include <llarp/pathbuilder.hpp>
#include <llarp/router_id.hpp>
#include <llarp/routing/handler.hpp>
#include <llarp/routing/message.hpp>
@ -22,6 +22,11 @@
#include <unordered_map>
#include <vector>
#define MAXHOPS (8)
#define DEFAULT_PATH_LIFETIME (10 * 60 * 1000)
#define PATH_BUILD_TIMEOUT (10 * 1000)
#define MESSAGE_PAD_SIZE (1024)
namespace llarp
{
namespace path
@ -193,7 +198,7 @@ namespace llarp
/// path id
PathID_t txID, rxID;
// router contact of router
llarp_rc router;
RouterContact rc;
// temp public encryption key
SecretKey commkey;
/// shared secret at this hop
@ -226,7 +231,7 @@ namespace llarp
llarp_time_t buildStarted;
PathStatus status;
Path(llarp_path_hops* path);
Path(const std::vector< RouterContact >& routers);
void
SetBuildResultHook(BuildResultHookFunc func);
@ -338,7 +343,7 @@ namespace llarp
/// track a path builder with this context
void
AddPathBuilder(llarp_pathbuilder_context* set);
AddPathBuilder(Builder* set);
void
AllowTransit();
@ -371,7 +376,7 @@ namespace llarp
bool
ForwardLRCM(const RouterID& nextHop,
std::deque< EncryptedFrame >& frames);
const std::array< EncryptedFrame, 8 >& frames);
bool
HopIsUs(const PubKey& k) const;
@ -386,7 +391,7 @@ namespace llarp
AddOwnPath(PathSet* set, Path* p);
void
RemovePathBuilder(llarp_pathbuilder_context* ctx);
RemovePathBuilder(Builder* ctx);
void
RemovePathSet(PathSet* set);
@ -423,7 +428,7 @@ namespace llarp
SyncTransitMap_t m_TransitPaths;
SyncTransitMap_t m_Paths;
SyncOwnedPathsMap_t m_OurPaths;
std::list< llarp_pathbuilder_context* > m_PathBuilders;
std::list< Builder* > m_PathBuilders;
bool m_AllowTransit;
};
} // namespace path

@ -1,62 +0,0 @@
#ifndef LLARP_PATHFINDER_H_
#define LLARP_PATHFINDER_H_
#include <llarp/buffer.h>
#include <llarp/path.h>
/**
* path_base.h
*
* path api functions
*/
/// 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, size_t numpaths,
size_t defaultNumHops);
/// 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 (user, nodedb, prevhop, result, hopnnumber) called in
// logic thread
typedef bool (*llarp_pathbuilder_select_hop_func)(void*, struct llarp_nodedb*,
struct llarp_rc*,
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;
// called when the path build started
llarp_pathbuilder_hook pathBuildStarted;
// 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);
#endif

@ -1,37 +1,41 @@
#ifndef LLARP_PATHBUILDER_HPP_
#define LLARP_PATHBUILDER_HPP_
#include <llarp/pathbuilder.h>
#include <llarp/router.h>
#include <llarp/path.hpp>
#include <llarp/pathset.hpp>
struct llarp_pathbuilder_context : public llarp::path::PathSet
namespace llarp
{
struct llarp_router* router;
struct llarp_dht_context* dht;
llarp::SecretKey enckey;
size_t numHops;
/// construct
llarp_pathbuilder_context(llarp_router* p_router,
struct llarp_dht_context* p_dht, size_t numPaths,
size_t numHops);
virtual ~llarp_pathbuilder_context();
virtual bool
SelectHop(llarp_nodedb* db, llarp_rc* prev, llarp_rc* cur, size_t hop);
virtual bool
ShouldBuildMore() const;
void
BuildOne();
void
ManualRebuild(size_t N);
virtual byte_t*
GetTunnelEncryptionSecretKey();
};
namespace path
{
struct Builder : public PathSet
{
struct llarp_router* router;
struct llarp_dht_context* dht;
llarp::SecretKey enckey;
size_t numHops;
/// construct
Builder(llarp_router* p_router, struct llarp_dht_context* p_dht,
size_t numPaths, size_t numHops);
virtual ~Builder();
virtual bool
SelectHop(llarp_nodedb* db, const RouterContact& prev, RouterContact& cur,
size_t hop);
virtual bool
ShouldBuildMore() const;
void
BuildOne();
void
ManualRebuild(size_t N);
virtual const byte_t*
GetTunnelEncryptionSecretKey() const;
};
} // namespace path
} // namespace llarp
#endif

@ -8,6 +8,7 @@
#include <llarp/routing/message.hpp>
#include <llarp/service/IntroSet.hpp>
#include <llarp/service/lookup.hpp>
#include <llarp/dht/messages/all.hpp>
#include <map>
#include <tuple>
@ -114,17 +115,9 @@ namespace llarp
}
virtual bool
SelectHop(llarp_nodedb* db, llarp_rc* prev, llarp_rc* cur,
SelectHop(llarp_nodedb* db, const RouterContact& prev, RouterContact& cur,
size_t hop) = 0;
static bool
SelectHopCallback(void* user, llarp_nodedb* db, llarp_rc* prev,
llarp_rc* cur, size_t hopno)
{
PathSet* self = static_cast< PathSet* >(user);
return self->SelectHop(db, prev, cur, hopno);
}
private:
typedef std::pair< RouterID, PathID_t > PathInfo_t;
typedef std::map< PathInfo_t, Path* > PathMap_t;

@ -3,11 +3,10 @@
#include <llarp/config.h>
#include <llarp/ev.h>
#include <llarp/logic.h>
#include <llarp/nodedb.h>
#include <llarp/pathbuilder.h>
#include <llarp/router_contact.h>
#include <llarp/threadpool.h>
#include <llarp/buffer.h>
struct llarp_nodedb;
struct llarp_router;
bool
@ -19,16 +18,6 @@ llarp_init_router(struct llarp_threadpool *worker,
struct llarp_ev_loop *netloop, struct llarp_logic *logic);
void
llarp_free_router(struct llarp_router **router);
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);

@ -1,115 +0,0 @@
#ifndef LLARP_RC_H
#define LLARP_RC_H
#include <llarp/address_info.h>
#include <llarp/crypto.h>
#include <llarp/exit_info.h>
#ifdef __cplusplus
#include <string>
#endif
// forward declare
struct llarp_alloc;
struct llarp_rc;
#define MAX_RC_SIZE (1024)
#define NICKLEN (32)
bool
llarp_rc_bdecode(struct llarp_rc *rc, llarp_buffer_t *buf);
bool
llarp_rc_bencode(const struct llarp_rc *rc, llarp_buffer_t *buf);
struct llarp_rc
{
struct llarp_ai_list *addrs;
// public encryption public key
byte_t enckey[PUBKEYSIZE];
// public signing public key
byte_t pubkey[PUBKEYSIZE];
struct llarp_xi_list *exits;
byte_t signature[SIGSIZE];
/// node nickname, yw kee
byte_t nickname[NICKLEN];
uint64_t last_updated;
#ifdef __cplusplus
bool
BEncode(llarp_buffer_t *buf) const
{
return llarp_rc_bencode(this, buf);
}
bool
BDecode(llarp_buffer_t *buf)
{
return llarp_rc_bdecode(this, buf);
}
bool
HasNick() const
{
return nickname[0] != 0;
}
std::string
Nick() const
{
const char *nick = (const char *)nickname;
return std::string(nick, strnlen(nick, sizeof(nickname)));
}
#endif
};
void
llarp_rc_free(struct llarp_rc *rc);
bool
llarp_rc_new(struct llarp_rc *rc);
bool
llarp_rc_verify_sig(struct llarp_crypto *crypto, struct llarp_rc *rc);
void
llarp_rc_copy(struct llarp_rc *dst, const struct llarp_rc *src);
bool
llarp_rc_is_public_router(const struct llarp_rc *const rc);
void
llarp_rc_set_addrs(struct llarp_rc *rc, struct llarp_alloc *mem,
struct llarp_ai_list *addr);
bool
llarp_rc_set_nickname(struct llarp_rc *rc, const char *name);
void
llarp_rc_set_pubenckey(struct llarp_rc *rc, const uint8_t *pubenckey);
void
llarp_rc_set_pubsigkey(struct llarp_rc *rc, const uint8_t *pubkey);
/// combo
void
llarp_rc_set_pubkey(struct llarp_rc *rc, const uint8_t *pubenckey,
const uint8_t *pubsigkey);
void
llarp_rc_sign(struct llarp_crypto *crypto, const byte_t *seckey,
struct llarp_rc *rc);
void
llarp_rc_clear(struct llarp_rc *rc);
bool
llarp_rc_addr_list_iter(struct llarp_ai_list_iter *iter, struct llarp_ai *ai);
bool
llarp_rc_read(const char *fpath, struct llarp_rc *result);
bool
llarp_rc_write(struct llarp_rc *rc, const char *our_rc_file);
#endif

@ -0,0 +1,67 @@
#ifndef LLARP_RC_HPP
#define LLARP_RC_HPP
#include <llarp/address_info.hpp>
#include <llarp/crypto.h>
#include <llarp/bencode.hpp>
#include <llarp/exit_info.hpp>
#include <list>
#define MAX_RC_SIZE (1024)
#define NICKLEN (32)
namespace llarp
{
struct RouterContact : public IBEncodeMessage
{
// advertised addresses
std::list< AddressInfo > addrs;
// public encryption public key
llarp::PubKey enckey;
// public signing public key
llarp::PubKey pubkey;
// advertised exits
std::list< ExitInfo > exits;
// signature
llarp::Signature signature;
/// node nickname, yw kee
llarp::AlignedBuffer< NICKLEN > nickname;
uint64_t last_updated;
bool
BEncode(llarp_buffer_t *buf) const;
bool
DecodeKey(llarp_buffer_t k, llarp_buffer_t *buf);
RouterContact &
operator=(const RouterContact &other);
bool
HasNick() const;
std::string
Nick() const;
bool
IsPublicRouter() const;
void
SetNick(const std::string &nick);
bool
VerifySignature(llarp_crypto *crypto) const;
bool
Sign(llarp_crypto *crypto, const llarp::SecretKey &secret);
bool
Read(const char *fname);
bool
Write(const char *fname) const;
};
} // namespace llarp
#endif

@ -5,12 +5,13 @@
#include <llarp/service/Identity.hpp>
#include <llarp/service/handler.hpp>
#include <llarp/service/protocol.hpp>
#include <llarp/path.hpp>
namespace llarp
{
namespace service
{
struct Endpoint : public llarp_pathbuilder_context,
struct Endpoint : public path::Builder,
public ILookupHolder,
public IDataHandler
{
@ -145,7 +146,7 @@ namespace llarp
typedef std::queue< PendingBuffer > PendingBufferQueue;
/// context needed to initiate an outbound hidden service session
struct OutboundContext : public llarp_pathbuilder_context
struct OutboundContext : public path::Builder
{
OutboundContext(const IntroSet& introSet, Endpoint* parent);
~OutboundContext();
@ -176,7 +177,8 @@ namespace llarp
HandlePathBuilt(path::Path* path);
bool
SelectHop(llarp_nodedb* db, llarp_rc* prev, llarp_rc* cur, size_t hop);
SelectHop(llarp_nodedb* db, const RouterContact& prev,
RouterContact& cur, size_t hop);
bool
HandleHiddenServiceFrame(const ProtocolFrame* frame);

@ -122,24 +122,6 @@ namespace llarp
return 1;
}
int
Context::IterateDatabase(struct llarp_nodedb_iter i)
{
return llarp_nodedb_iterate_all(nodedb, i);
}
bool
Context::PutDatabase(struct llarp_rc *rc)
{
return llarp_nodedb_put_rc(nodedb, rc);
}
struct llarp_rc *
Context::GetDatabase(const byte_t *pk)
{
return llarp_nodedb_get_rc(nodedb, pk);
}
int
Context::Setup()
{
@ -371,25 +353,6 @@ extern "C"
return ptr->ctx->GetDatabase(pk);
}
struct llarp_rc *
llarp_main_getLocalRC(struct llarp_main *ptr)
{
//
/*
llarp_config_iterator iter;
iter.user = this;
iter.visit = &iter_config;
llarp_config_iter(ctx->config, &iter);
*/
llarp_rc *rc = new llarp_rc;
llarp_rc_new(rc);
llarp::LogInfo("Loading ", ptr->ctx->conatctFile);
if(llarp_rc_read(ptr->ctx->conatctFile, rc))
return rc;
else
return nullptr;
}
void
llarp_main_checkOnline(void *u, uint64_t orig, uint64_t left)
{
@ -423,7 +386,6 @@ extern "C"
request->first = true;
llarp::LogInfo("llarp_main_queryDHT_online - We're online");
llarp::LogInfo("llarp_main_queryDHT_online - Querying DHT");
llarp_dht_lookup_router(request->ptr->ctx->router->dht, request->job);
}
}

@ -1,6 +1,6 @@
#include <llarp/crypto_async.h>
#include <llarp/mem.h>
#include <llarp/router_contact.h>
#include <llarp/router_contact.hpp>
#include <string.h>
#include <llarp/crypto.hpp>
#include <llarp/router_id.hpp>

@ -19,15 +19,6 @@ llarp_dht_context_free(struct llarp_dht_context *ctx)
delete ctx;
}
void
__llarp_dht_put_peer(struct llarp_dht_context *ctx, struct llarp_rc *rc)
{
llarp::dht::RCNode n(rc);
llarp::LogDebug("Adding ", n.ID, " to DHT");
ctx->impl.nodes->PutNode(n);
}
void
__llarp_dht_remove_peer(struct llarp_dht_context *ctx, const byte_t *id)
{
@ -47,14 +38,3 @@ llarp_dht_context_start(struct llarp_dht_context *ctx, const byte_t *key)
{
ctx->impl.Init(key, ctx->parent, 20000);
}
void
llarp_dht_lookup_router(struct llarp_dht_context *ctx,
struct llarp_router_lookup_job *job)
{
job->dht = ctx;
job->found = false;
llarp_rc_clear(&job->result);
llarp_logic_queue_job(ctx->parent->logic,
{job, &llarp::dht::Context::queue_router_lookup});
}

@ -70,7 +70,8 @@ namespace llarp
llarp::LogInfo("got ", valuesFound.size(), " routers from exploration");
for(const auto &pk : valuesFound)
{
if(llarp_nodedb_get_rc(parent->router->nodedb, pk) == nullptr)
RouterContact rc;
if(!llarp_nodedb_get_rc(parent->router->nodedb, pk, rc))
{
// try connecting to it we don't know it
// this triggers a dht lookup
@ -191,7 +192,7 @@ namespace llarp
{
// we are the target, give them our RC
replies.push_back(
new GotRouterMessage(requester, txid, &router->rc, false));
new GotRouterMessage(requester, txid, {router->rc}, false));
return;
}
Key_t next;
@ -202,7 +203,7 @@ namespace llarp
{
// we know it
replies.push_back(new GotRouterMessage(
requester, txid, nodes->nodes[target].rc, false));
requester, txid, {nodes->nodes[target].rc}, false));
}
else if(recursive) // are we doing a recursive lookup?
{
@ -216,22 +217,19 @@ namespace llarp
{
// no we are closer to the target so tell requester it's not there
// so they switch to iterative lookup
replies.push_back(
new GotRouterMessage(requester, txid, nullptr, false));
replies.push_back(new GotRouterMessage(requester, txid, {}, false));
}
}
else // iterative lookup and we don't have it tell them we don't have
// the target router
{
replies.push_back(
new GotRouterMessage(requester, txid, nullptr, false));
replies.push_back(new GotRouterMessage(requester, txid, {}, false));
}
}
else
{
// we don't know it and have no closer peers to ask
replies.push_back(
new GotRouterMessage(requester, txid, nullptr, false));
replies.push_back(new GotRouterMessage(requester, txid, {}, false));
}
}
@ -600,15 +598,15 @@ namespace llarp
return true;
}
struct RecursiveRouterLookup : public TX< RouterID, llarp_rc >
struct RecursiveRouterLookup : public TX< RouterID, RouterContact >
{
llarp_router_lookup_job *job;
RouterLookupHandler resultHandler;
RecursiveRouterLookup(const TXOwner &whoasked, const RouterID &target,
Context *ctx, llarp_router_lookup_job *j)
: TX< RouterID, llarp_rc >(whoasked, target, ctx)
Context *ctx, RouterLookupHandler result)
: TX< RouterID, RouterContact >(whoasked, target, ctx)
, resultHandler(result)
{
job = j;
peersAsked.insert(ctx->OurKey());
}
@ -641,32 +639,16 @@ namespace llarp
void
SendReply()
{
if(job)
if(resultHandler)
{
job->found = false;
if(valuesFound.size())
{
job->found =
memcmp(valuesFound[0].pubkey, job->target, PUBKEYSIZE) == 0;
if(job->found)
llarp_rc_copy(&job->result, &valuesFound[0]);
}
if(job->hook)
job->hook(job);
else
delete job;
resultHandler(valuesFound);
}
else
{
llarp_rc *found = nullptr;
if(valuesFound.size())
found = &valuesFound[0];
parent->DHTSendTo(
whoasked.node,
new GotRouterMessage({}, whoasked.txid, found, false));
new GotRouterMessage({}, whoasked.txid, valuesFound, false));
}
for(auto rc : valuesFound)
llarp_rc_free(&rc);
}
};
@ -674,38 +656,15 @@ namespace llarp
Context::LookupRouterRecursive(const RouterID &target,
const Key_t &whoasked, uint64_t txid,
const Key_t &askpeer,
llarp_router_lookup_job *job)
RouterLookupHandler handler)
{
TXOwner asker(whoasked, txid);
TXOwner peer(askpeer, ++ids);
auto tx = pendingRouterLookups.NewTX(
peer, target, new RecursiveRouterLookup(asker, target, this, job));
peer, target,
new RecursiveRouterLookup(asker, target, this, handler));
tx->Start(peer);
}
void
Context::LookupRouterViaJob(llarp_router_lookup_job *job)
{
Key_t peer;
if(nodes->FindClosest(job->target, peer))
LookupRouterRecursive(job->target, ourKey, 0, peer, job);
else if(job->hook)
{
job->found = false;
job->hook(job);
}
else
delete job;
}
void
Context::queue_router_lookup(void *user)
{
struct llarp_router_lookup_job *job =
static_cast< llarp_router_lookup_job * >(user);
job->dht->impl.LookupRouterViaJob(job);
}
} // namespace dht
} // namespace llarp

@ -9,60 +9,6 @@ namespace llarp
{
namespace dht
{
struct PathLookupInformer
{
llarp_router *router;
PathID_t pathID;
uint64_t txid;
PathLookupInformer(llarp_router *r, const PathID_t &id, uint64_t tx)
: router(r), pathID(id), txid(tx)
{
}
void
SendReply(llarp::routing::IMessage *msg)
{
auto path = router->paths.GetByUpstream(router->pubkey(), pathID);
if(path == nullptr)
{
llarp::LogWarn("Path not found for relayed DHT message txid=", txid,
" pathid=", pathID);
return;
}
if(!path->SendRoutingMessage(msg, router))
llarp::LogWarn("Failed to send reply for relayed DHT message txid=",
txid, "pathid=", pathID);
}
static void
InformReply(llarp_router_lookup_job *job)
{
PathLookupInformer *self =
static_cast< PathLookupInformer * >(job->user);
llarp::routing::DHTMessage reply;
if(job->found)
{
if(llarp_rc_verify_sig(&self->router->crypto, &job->result))
{
reply.M.push_back(new GotRouterMessage(job->target, self->txid,
&job->result, false));
}
llarp_rc_free(&job->result);
llarp_rc_clear(&job->result);
}
else
{
reply.M.push_back(
new GotRouterMessage(job->target, self->txid, nullptr, false));
}
self->SendReply(&reply);
// TODO: is this okay?
delete self;
delete job;
}
};
bool
RelayedFindRouterMessage::HandleMessage(
llarp_dht_context *ctx, std::vector< IMessage * > &replies) const
@ -75,24 +21,16 @@ namespace llarp
if(path)
{
replies.push_back(
new GotRouterMessage(K.data(), txid, &dht.router->rc, false));
new GotRouterMessage(K.data(), txid, {dht.router->rc}, false));
return true;
}
return false;
}
llarp_router_lookup_job *job = new llarp_router_lookup_job;
PathLookupInformer *informer =
new PathLookupInformer(dht.router, pathID, txid);
job->user = informer;
job->hook = &PathLookupInformer::InformReply;
job->found = false;
llarp_rc_clear(&job->result);
job->dht = ctx;
memcpy(job->target, K, sizeof(job->target));
Key_t peer;
Key_t k = K.data();
if(dht.nodes->FindClosest(k, peer))
dht.LookupRouterRecursive(K, dht.OurKey(), txid, peer, job);
dht.LookupRouterForPath(K, txid, pathID, peer);
return true;
}

@ -9,9 +9,6 @@ namespace llarp
{
GotRouterMessage::~GotRouterMessage()
{
for(auto rc : R)
llarp_rc_free(&rc);
R.clear();
}
bool

@ -17,17 +17,17 @@ namespace llarp
Encrypted::Encrypted(const byte_t* buf, size_t sz) : _sz(sz)
{
_data = new byte_t[sz];
if(sz > MAX_SIZE)
throw std::logic_error("encrypted frame too big");
if(buf)
memcpy(data(), buf, sz);
else
llarp::Zero(data(), sz);
UpdateBuffer();
}
Encrypted::~Encrypted()
{
if(_data)
delete[] _data;
}
Encrypted::Encrypted(size_t sz) : Encrypted(nullptr, sz)

@ -94,22 +94,30 @@ frame_state::got_xmit(frame_header hdr, size_t sz)
auto itr = rx.find(h);
if(itr == rx.end())
{
auto msg = rx.insert(std::make_pair(h,
std::unique_ptr< transit_message >(
new transit_message(x))))
.first->second.get();
rxIDs.insert(std::make_pair(id, h));
llarp::LogDebug("got message XMIT with ", (int)x.numfrags(),
" fragment"
"s");
// inserted, put last fragment
msg->put_lastfrag(hdr.data() + sizeof(x.buffer), x.lastfrag());
push_ackfor(id, 0);
if(x.numfrags() == 0)
if(x.numfrags() > 0)
{
return inbound_frame_complete(id);
auto msg = rx.insert(std::make_pair(h,
std::unique_ptr< transit_message >(
new transit_message(x))))
.first->second.get();
rxIDs.insert(std::make_pair(id, h));
llarp::LogDebug("got message XMIT with ", (int)x.numfrags(),
" fragment"
"s");
// inserted, put last fragment
msg->put_lastfrag(hdr.data() + sizeof(x.buffer), x.lastfrag());
push_ackfor(id, 0);
return true;
}
else
{
// handle zero fragment message immediately
std::unique_ptr< transit_message > msg =
std::unique_ptr< transit_message >(new transit_message(x));
msg->put_lastfrag(hdr.data() + sizeof(x.buffer), x.lastfrag());
push_ackfor(id, 0);
return inbound_frame_complete(msg);
}
return true;
}
else
llarp::LogWarn("duplicate XMIT h=", llarp::ShortHash(h));
@ -170,7 +178,10 @@ frame_state::got_frag(frame_header hdr, size_t sz)
if(itr->second->completed())
{
push_ackfor(msgid, mask);
return inbound_frame_complete(msgid);
bool result = inbound_frame_complete(itr->second);
rxIDs.erase(idItr);
rx.erase(itr);
return result;
}
else if(itr->second->should_send_ack(llarp_time_now_ms()))
{
@ -191,14 +202,15 @@ frame_state::push_ackfor(uint64_t id, uint32_t bitmask)
}
bool
frame_state::inbound_frame_complete(uint64_t id)
frame_state::inbound_frame_complete(
const std::unique_ptr< transit_message > &rxmsg)
{
bool success = false;
std::vector< byte_t > msg;
std::unique_ptr< transit_message > rxmsg = std::move(rx[rxIDs[id]]);
rx.erase(rxIDs[id]);
rxIDs.erase(id);
llarp::ShortHash digest;
auto id = rxmsg->msginfo.msgid();
if(rxmsg->reassemble(msg))
{
auto router = Router();
@ -334,8 +346,8 @@ frame_state::process(byte_t *buf, size_t sz)
void
frame_state::queue_tx(uint64_t id, transit_message *msg)
{
tx.insert(std::make_pair(id, std::unique_ptr< transit_message >(msg)));
msg->generate_xmit(sendqueue, txflags);
tx.insert(std::make_pair(id, std::unique_ptr< transit_message >(msg)));
// msg->retransmit_frags(sendqueue, txflags);
}

@ -111,8 +111,7 @@ llarp_link::TickSessions()
{
if(itr->second->Tick(now))
{
if(itr->second->get_remote_router())
m_Connected.erase(itr->second->get_remote_router()->pubkey);
m_Connected.erase(itr->second->get_remote_router().pubkey);
itr = m_sessions.erase(itr);
}
else
@ -289,13 +288,13 @@ llarp_link::issue_cleanup_timer(uint64_t timeout)
}
void
llarp_link::get_our_address(llarp_ai* addr)
llarp_link::get_our_address(llarp::AddressInfo& addr)
{
addr->rank = 1;
strncpy(addr->dialect, "IWP", sizeof(addr->dialect));
memcpy(addr->enc_key, pubkey(), 32);
memcpy(addr->ip.s6_addr, this->addr.addr6(), 16);
addr->port = this->addr.port();
addr.rank = 1;
addr.dialect = "IWP";
addr.pubkey = pubkey();
addr.port = this->addr.port();
memcpy(addr.ip.s6_addr, this->addr.addr6(), 16);
}
void
@ -411,7 +410,7 @@ llarp_link::try_establish(struct llarp_link_establish_job* job)
visit_session(dst, [job](const std::unique_ptr< llarp_link_session >& s) {
s->establish_job = job;
s->frame.alive(); // mark it alive
s->introduce(job->ai.enc_key);
s->introduce(job->ai.pubkey);
});
return true;
}

@ -35,7 +35,6 @@ llarp_link_session::llarp_link_session(llarp_link *l, const byte_t *seckey,
eph_seckey = seckey;
else
crypto->encryption_keygen(eph_seckey);
llarp_rc_clear(&remote_router);
crypto->randbytes(token, 32);
frame.alive();
working.store(false);
@ -44,7 +43,6 @@ llarp_link_session::llarp_link_session(llarp_link *l, const byte_t *seckey,
llarp_link_session::~llarp_link_session()
{
llarp_rc_free(&remote_router);
frame.clear();
}
@ -72,6 +70,8 @@ llarp_link_session::sendto(llarp_buffer_t msg)
bool
llarp_link_session::timedout(llarp_time_t now, llarp_time_t timeout)
{
if(frame.lastEvent == 0)
return false;
if(now <= frame.lastEvent)
return false;
auto diff = now - frame.lastEvent;
@ -127,10 +127,10 @@ llarp_link_session::session_established()
llarp_logic_cancel_call(serv->logic, establish_job_id);
}
llarp_rc *
llarp_link_session::get_remote_router()
const llarp::RouterContact &
llarp_link_session::get_remote_router() const
{
return &remote_router;
return remote_router;
}
void
@ -150,16 +150,16 @@ bool
llarp_link_session::CheckRCValid()
{
// verify signatuire
if(!llarp_rc_verify_sig(crypto, &remote_router))
if(!remote_router.VerifySignature(crypto))
return false;
auto &list = remote_router.addrs->list;
if(list.size() == 0) // the remote node is a client node so accept it
if(remote_router.addrs.size()
== 0) // the remote node is a client node so accept it
return true;
// check if the RC owns a pubkey that we are using
for(auto &ai : list)
for(auto &ai : remote_router.addrs)
{
if(memcmp(ai.enc_key, remote, PUBKEYSIZE) == 0)
if(ai.pubkey == remote)
return true;
}
return false;
@ -240,7 +240,6 @@ handle_verify_introack(iwp_async_introack *introack)
{
// invalid signature
llarp::LogError("introack verify failed from ", link->addr);
link->serv->remove_intro_from(link->addr);
return;
}
// cancel resend
@ -271,7 +270,8 @@ handle_establish_timeout(void *user, uint64_t orig, uint64_t left)
// timer timeout
job->session = nullptr;
}
job->result(job);
if(!self->working)
job->result(job);
}
}
@ -425,12 +425,10 @@ llarp_link_session::keepalive()
void
llarp_link_session::EncryptOutboundFrames()
{
llarp_link_session *self = this;
outboundFrames.Process([self](iwp_async_frame *frame) {
outboundFrames.Process([&](iwp_async_frame *frame) {
if(iwp_encrypt_frame(frame))
if(llarp_ev_udp_sendto(self->udp, self->addr, frame->buf, frame->sz)
== -1)
llarp::LogError("sendto ", self->addr, " failed");
if(llarp_ev_udp_sendto(udp, addr, frame->buf, frame->sz) == -1)
llarp::LogError("sendto ", addr, " failed");
});
}
@ -753,6 +751,8 @@ llarp_link_session::encrypt_frame_async_send(const void *buf, size_t sz)
{
// 64 bytes frame overhead for nonce and hmac
auto frame = alloc_frame(nullptr, sz + 64);
if(frame == nullptr)
return;
memcpy(frame->buf + 64, buf, sz);
// maybe add upto 128 random bytes to the packet
auto padding = llarp_randint() % MAX_PAD;

@ -5,7 +5,7 @@ namespace llarp
/// encode Link Introduce Message onto a buffer
/// if router is nullptr then the LIM's r member is omitted.
bool
EncodeLIM(llarp_buffer_t* buff, llarp_rc* router)
EncodeLIM(llarp_buffer_t* buff, const llarp::RouterContact* router)
{
if(!bencode_start_dict(buff))
return false;
@ -21,7 +21,7 @@ namespace llarp
{
if(!bencode_write_bytestring(buff, "r", 1))
return false;
if(!llarp_rc_bencode(router, buff))
if(!router->BEncode(buff))
return false;
}

@ -3,14 +3,14 @@
#include <llarp/bencode.h>
#include <llarp/buffer.h>
#include <llarp/router_contact.h>
#include <llarp/router_contact.hpp>
namespace llarp
{
/// encode Link Introduce Message onto a buffer
/// if router is nullptr then the LIM's r member is omitted.
bool
EncodeLIM(llarp_buffer_t* buff, llarp_rc* router);
EncodeLIM(llarp_buffer_t* buff, const RouterContact* router);
} // namespace llarp
#endif

@ -1,5 +1,5 @@
#include <llarp/bencode.h>
#include <llarp/router_contact.h>
#include <llarp/router_contact.hpp>
#include <llarp/messages/link_intro.hpp>
#include "logger.hpp"
#include "router.hpp"
@ -15,13 +15,9 @@ namespace llarp
{
if(llarp_buffer_eq(key, "r"))
{
if(!llarp_rc_bdecode(RC, buf))
{
llarp::LogWarn("failed to decode RC");
if(!RC.BDecode(buf))
return false;
}
remote = (byte_t*)RC->pubkey;
llarp::LogDebug("decoded RC from ", remote);
hasRC = true;
return true;
}
else if(llarp_buffer_eq(key, "v"))
@ -55,12 +51,11 @@ namespace llarp
if(!bencode_write_bytestring(buf, "i", 1))
return false;
if(RC)
if(hasRC)
{
if(!bencode_write_bytestring(buf, "r", 1))
return false;
if(!llarp_rc_bencode(RC, buf))
return false;
return RC.BEncode(buf);
}
if(!bencode_write_version_entry(buf))
@ -72,7 +67,7 @@ namespace llarp
bool
LinkIntroMessage::HandleMessage(llarp_router* router) const
{
router->async_verify_RC(RC, !llarp_rc_is_public_router(RC));
router->async_verify_RC(RC, !RC.IsPublicRouter());
return true;
}
} // namespace llarp

@ -1,4 +1,4 @@
#include <llarp/router_contact.h>
#include <llarp/router_contact.hpp>
#include <llarp/messages.hpp>
#include "buffer.hpp"
#include "llarp/iwp/session.hpp"
@ -88,8 +88,7 @@ namespace llarp
RouterID
InboundMessageParser::GetCurrentFrom()
{
auto rc = from->get_remote_router();
return rc->pubkey;
return from->get_remote_router().pubkey;
}
bool

@ -1,6 +1,6 @@
#include <llarp/crypto_async.h>
#include <llarp/nodedb.h>
#include <llarp/router_contact.h>
#include <llarp/nodedb.hpp>
#include <llarp/router_contact.hpp>
#include <fstream>
#include <llarp/crypto.hpp>
@ -22,89 +22,36 @@ struct llarp_nodedb
llarp_crypto *crypto;
// std::map< llarp::pubkey, llarp_rc > entries;
std::unordered_map< llarp::PubKey, llarp_rc, llarp::PubKey::Hash > entries;
llarp::util::Mutex access;
std::unordered_map< llarp::PubKey, llarp::RouterContact, llarp::PubKey::Hash >
entries;
fs::path nodePath;
void
Clear()
{
auto itr = entries.begin();
while(itr != entries.end())
{
llarp_rc_clear(&itr->second);
itr = entries.erase(itr);
}
}
llarp_rc *
getRC(const llarp::PubKey &pk)
{
return &entries.at(pk);
llarp::util::Lock lock(access);
entries.clear();
}
bool
Has(const llarp::PubKey &pk) const
Get(const llarp::PubKey &pk, llarp::RouterContact &result)
{
return entries.find(pk) != entries.end();
llarp::util::Lock lock(access);
auto itr = entries.find(pk);
if(itr == entries.end())
return false;
result = itr->second;
return true;
}
/*
bool
Has(const byte_t *pk)
{
llarp::PubKey test(pk);
auto itr = this->entries.begin();
while(itr != this->entries.end())
{
llarp::LogInfo("Has byte_t [", test.size(), "] vs [", itr->first.size(),
"]"); if (memcmp(test.data(), itr->first.data(), 32) == 0) {
llarp::LogInfo("Match");
}
itr++;
}
return entries.find(pk) != entries.end();
}
*/
bool
pubKeyExists(llarp_rc *rc) const
Has(const llarp::PubKey &pk)
{
// extract pk from rc
llarp::PubKey pk = rc->pubkey;
// return true if we found before end
llarp::util::Lock lock(access);
return entries.find(pk) != entries.end();
}
bool
check(llarp_rc *rc)
{
if(!pubKeyExists(rc))
{
// we don't have it
return false;
}
llarp::PubKey pk = rc->pubkey;
// TODO: zero out any fields you don't want to compare
// XXX: make a copy and then do modifications on the copy
// touching external data in here is HARAM >:[
// serialize both and memcmp
byte_t nodetmp[MAX_RC_SIZE];
auto nodebuf = llarp::StackBuffer< decltype(nodetmp) >(nodetmp);
if(llarp_rc_bencode(&entries[pk], &nodebuf))
{
byte_t paramtmp[MAX_RC_SIZE];
auto parambuf = llarp::StackBuffer< decltype(paramtmp) >(paramtmp);
if(llarp_rc_bencode(rc, &parambuf))
{
if(nodebuf.sz == parambuf.sz)
return memcmp(&parambuf, &nodebuf, parambuf.sz) == 0;
}
}
return false;
}
std::string
getRCFilePath(const byte_t *pubkey) const
{
@ -119,40 +66,34 @@ struct llarp_nodedb
return filepath.string();
}
/// insert and write to disk
bool
setRC(llarp_rc *rc)
Insert(const llarp::RouterContact &rc)
{
byte_t tmp[MAX_RC_SIZE];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
{
llarp::util::Lock lock(access);
entries.insert(std::make_pair(rc.pubkey, rc));
}
if(!rc.BEncode(&buf))
return false;
// extract pk from rc
llarp::PubKey pk = rc->pubkey;
// set local db entry to have a copy we own
llarp_rc entry;
llarp::Zero(&entry, sizeof(entry));
llarp_rc_copy(&entry, rc);
entries.insert(std::make_pair(pk, entry));
if(llarp_rc_bencode(&entry, &buf))
buf.sz = buf.cur - buf.base;
auto filepath = getRCFilePath(rc.pubkey);
llarp::LogDebug("saving RC.pubkey ", filepath);
std::ofstream ofs(
filepath,
std::ofstream::out & std::ofstream::binary & std::ofstream::trunc);
ofs.write((char *)buf.base, buf.sz);
ofs.close();
if(!ofs)
{
buf.sz = buf.cur - buf.base;
auto filepath = getRCFilePath(pk);
llarp::LogDebug("saving RC.pubkey ", filepath);
std::ofstream ofs(
filepath,
std::ofstream::out & std::ofstream::binary & std::ofstream::trunc);
ofs.write((char *)buf.base, buf.sz);
ofs.close();
if(!ofs)
{
llarp::LogError("Failed to write: ", filepath);
return false;
}
llarp::LogDebug("saved RC.pubkey: ", filepath);
return true;
llarp::LogError("Failed to write: ", filepath);
return false;
}
return false;
llarp::LogDebug("saved RC.pubkey: ", filepath);
return true;
}
ssize_t
@ -197,28 +138,30 @@ struct llarp_nodedb
{
if(fpath.extension() != RC_FILE_EXT)
return false;
llarp_rc rc;
llarp_rc_clear(&rc);
llarp::RouterContact rc;
if(!llarp_rc_read(fpath.string().c_str(), &rc))
if(!rc.Read(fpath.string().c_str()))
{
llarp::LogError("Signature read failed", fpath);
llarp::LogError("failed to read file ", fpath);
return false;
}
if(!llarp_rc_verify_sig(crypto, &rc))
if(!rc.VerifySignature(crypto))
{
llarp::LogError("Signature verify failed", fpath);
return false;
}
llarp::PubKey pk(rc.pubkey);
entries[pk] = rc;
{
llarp::util::Lock lock(access);
entries.insert(std::make_pair(rc.pubkey, rc));
}
return true;
}
bool
iterate(struct llarp_nodedb_iter i)
{
i.index = 0;
i.index = 0;
llarp::util::Lock lock(access);
auto itr = entries.begin();
while(itr != entries.end())
{
@ -263,7 +206,7 @@ disk_threadworker_setRC(void *user)
{
llarp_async_verify_rc *verify_request =
static_cast< llarp_async_verify_rc * >(user);
verify_request->valid = verify_request->nodedb->setRC(&verify_request->rc);
verify_request->valid = verify_request->nodedb->Insert(verify_request->rc);
if(verify_request->logic)
llarp_logic_queue_job(verify_request->logic,
{verify_request, &logic_threadworker_callback});
@ -276,9 +219,9 @@ crypto_threadworker_verifyrc(void *user)
llarp_async_verify_rc *verify_request =
static_cast< llarp_async_verify_rc * >(user);
verify_request->valid =
llarp_rc_verify_sig(verify_request->nodedb->crypto, &verify_request->rc);
verify_request->rc.VerifySignature(verify_request->nodedb->crypto);
// if it's valid we need to set it
if(verify_request->valid && llarp_rc_is_public_router(&verify_request->rc))
if(verify_request->valid && verify_request->rc.IsPublicRouter())
{
llarp::LogDebug("RC is valid, saving to disk");
llarp_threadpool_queue_job(verify_request->diskworker,
@ -310,8 +253,7 @@ nodedb_async_load_rc(void *user)
job->loaded = job->nodedb->loadfile(fpath);
if(job->loaded)
{
llarp_rc_clear(&job->rc);
llarp_rc_copy(&job->rc, job->nodedb->getRC(job->pubkey));
job->nodedb->Get(job->pubkey, job->result);
}
llarp_logic_queue_job(job->logic, {job, &nodedb_inform_load_rc});
}
@ -384,14 +326,6 @@ llarp_nodedb_load_dir(struct llarp_nodedb *n, const char *dir)
return n->Load(dir);
}
/// c api for nodedb::setRC
/// maybe better to use llarp_nodedb_async_verify
bool
llarp_nodedb_put_rc(struct llarp_nodedb *n, struct llarp_rc *rc)
{
return n->setRC(rc);
}
int
llarp_nodedb_iterate_all(struct llarp_nodedb *n, struct llarp_nodedb_iter i)
{
@ -419,14 +353,12 @@ llarp_nodedb_async_load_rc(struct llarp_async_load_rc *job)
}
*/
struct llarp_rc *
llarp_nodedb_get_rc(struct llarp_nodedb *n, const byte_t *pk)
bool
llarp_nodedb_get_rc(struct llarp_nodedb *n, const llarp::RouterID &pk,
llarp::RouterContact &result)
{
// llarp::LogInfo("llarp_nodedb_get_rc [", pk, "]");
if(n->Has(pk))
return n->getRC(pk);
else
return nullptr;
return n->Get(pk, result);
}
size_t
@ -436,14 +368,15 @@ llarp_nodedb_num_loaded(struct llarp_nodedb *n)
}
void
llarp_nodedb_select_random_hop(struct llarp_nodedb *n, struct llarp_rc *prev,
struct llarp_rc *result, size_t N)
llarp_nodedb_select_random_hop(struct llarp_nodedb *n,
const llarp::RouterContact &prev,
llarp::RouterContact &result, size_t N)
{
/// checking for "guard" status for N = 0 is done by caller inside of
/// pathbuilder's scope
auto sz = n->entries.size();
if(prev)
if(N)
{
do
{
@ -451,13 +384,14 @@ llarp_nodedb_select_random_hop(struct llarp_nodedb *n, struct llarp_rc *prev,
if(sz > 1)
{
auto idx = llarp_randint() % sz;
std::advance(itr, idx);
if(idx)
std::advance(itr, idx - 1);
}
if(memcmp(prev->pubkey, itr->second.pubkey, PUBKEYSIZE) == 0)
if(prev.pubkey == itr->second.pubkey)
continue;
if(itr->second.addrs && llarp_ai_list_size(itr->second.addrs))
if(itr->second.addrs.size())
{
llarp_rc_copy(result, &itr->second);
result = itr->second;
return;
}
} while(true);
@ -468,8 +402,9 @@ llarp_nodedb_select_random_hop(struct llarp_nodedb *n, struct llarp_rc *prev,
if(sz > 1)
{
auto idx = llarp_randint() % sz;
std::advance(itr, idx);
if(idx)
std::advance(itr, idx - 1);
}
llarp_rc_copy(result, &itr->second);
result = itr->second;
}
}

@ -62,15 +62,11 @@ namespace llarp
bool
PathContext::ForwardLRCM(const RouterID& nextHop,
std::deque< EncryptedFrame >& frames)
const std::array< EncryptedFrame, 8 >& frames)
{
llarp::LogDebug("fowarding LRCM to ", nextHop);
LR_CommitMessage* msg = new LR_CommitMessage();
while(frames.size())
{
msg->frames.push_back(frames.front());
frames.pop_front();
}
msg->frames = frames;
return m_Router->SendToOrQueue(nextHop, msg);
}
template < typename Map_t, typename Key_t, typename CheckValue_t,
@ -290,7 +286,7 @@ namespace llarp
}
void
PathContext::AddPathBuilder(llarp_pathbuilder_context* ctx)
PathContext::AddPathBuilder(Builder* ctx)
{
m_PathBuilders.push_back(ctx);
}
@ -311,7 +307,7 @@ namespace llarp
}
void
PathContext::RemovePathBuilder(llarp_pathbuilder_context* ctx)
PathContext::RemovePathBuilder(Builder* ctx)
{
m_PathBuilders.remove(ctx);
RemovePathSet(ctx);
@ -319,31 +315,30 @@ namespace llarp
PathHopConfig::PathHopConfig()
{
llarp_rc_clear(&router);
}
PathHopConfig::~PathHopConfig()
{
llarp_rc_free(&router);
}
Path::Path(llarp_path_hops* h) : hops(h->numHops)
Path::Path(const std::vector< RouterContact >& h) : hops(h.size())
{
for(size_t idx = 0; idx < h->numHops; ++idx)
size_t hsz = h.size();
for(size_t idx = 0; idx < hsz; ++idx)
{
llarp_rc_copy(&hops[idx].router, &h->hops[idx].router);
hops[idx].rc = h[idx];
hops[idx].txID.Randomize();
hops[idx].rxID.Randomize();
}
for(size_t idx = 0; idx < h->numHops - 1; ++idx)
for(size_t idx = 0; idx < hsz - 1; ++idx)
{
hops[idx].txID = hops[idx + 1].rxID;
}
// initialize parts of the introduction
intro.router = hops[h->numHops - 1].router.pubkey;
intro.router = hops[hsz - 1].rc.pubkey;
// TODO: or is it rxid ?
intro.pathID = hops[h->numHops - 1].txID;
intro.pathID = hops[hsz - 1].txID;
}
void
@ -355,7 +350,7 @@ namespace llarp
RouterID
Path::Endpoint() const
{
return hops[hops.size() - 1].router.pubkey;
return hops[hops.size() - 1].rc.pubkey;
}
const PathID_t&
@ -379,7 +374,7 @@ namespace llarp
RouterID
Path::Upstream() const
{
return hops[0].router.pubkey;
return hops[0].rc.pubkey;
}
void

@ -1,4 +1,4 @@
#include <llarp/nodedb.h>
#include <llarp/nodedb.hpp>
#include <llarp/path.hpp>
#include <llarp/pathbuilder.hpp>
@ -44,7 +44,7 @@ namespace llarp
ctx->crypto->encryption_keygen(hop.commkey);
hop.nonce.Randomize();
// do key exchange
if(!ctx->crypto->dh_client(hop.shared, hop.router.enckey, hop.commkey,
if(!ctx->crypto->dh_client(hop.shared, hop.rc.enckey, hop.commkey,
hop.nonce))
{
llarp::LogError("Failed to generate shared key for path build");
@ -59,11 +59,11 @@ namespace llarp
if(isFarthestHop)
{
hop.upstream = hop.router.pubkey;
hop.upstream = hop.rc.pubkey;
}
else
{
hop.upstream = ctx->path->hops[ctx->idx].router.pubkey;
hop.upstream = ctx->path->hops[ctx->idx].rc.pubkey;
}
// build record
@ -87,7 +87,7 @@ namespace llarp
// use ephameral keypair for frame
SecretKey framekey;
ctx->crypto->encryption_keygen(framekey);
if(!frame.EncryptInPlace(framekey, hop.router.enckey, ctx->crypto))
if(!frame.EncryptInPlace(framekey, hop.rc.enckey, ctx->crypto))
{
llarp::LogError("Failed to encrypt LRCR");
return;
@ -123,16 +123,14 @@ namespace llarp
for(size_t idx = 0; idx < MAXHOPS; ++idx)
{
LRCM->frames.emplace_back();
LRCM->frames.back().Randomize();
LRCM->frames[idx].Randomize();
}
llarp_threadpool_queue_job(pool, {this, &GenerateNextKey});
}
};
void
pathbuilder_generated_keys(
AsyncPathKeyExchangeContext< llarp_pathbuild_job >* ctx)
pathbuilder_generated_keys(AsyncPathKeyExchangeContext< path::Builder >* ctx)
{
auto remote = ctx->path->Upstream();
auto router = ctx->user->router;
@ -148,131 +146,104 @@ namespace llarp
router->PersistSessionUntil(remote, ctx->path->ExpireTime());
// add own path
router->paths.AddOwnPath(ctx->pathset, ctx->path);
ctx->user->pathBuildStarted(ctx->user);
}
void
pathbuilder_start_build(void* user)
namespace path
{
llarp_pathbuild_job* job = static_cast< llarp_pathbuild_job* >(user);
// select hops
size_t idx = 0;
llarp_rc* prev = nullptr;
while(idx < job->hops.numHops)
Builder::Builder(llarp_router* p_router, struct llarp_dht_context* p_dht,
size_t pathNum, size_t hops)
: llarp::path::PathSet(pathNum)
, router(p_router)
, dht(p_dht)
, numHops(hops)
{
llarp_rc* rc = &job->hops.hops[idx].router;
llarp_rc_clear(rc);
if(!job->selectHop(job->user, job->router->nodedb, prev, rc, idx))
{
/// TODO: handle this failure properly
llarp::LogWarn("Failed to select hop ", idx);
return;
}
prev = rc;
++idx;
p_router->paths.AddPathBuilder(this);
p_router->crypto.encryption_keygen(enckey);
}
// async generate keys
AsyncPathKeyExchangeContext< llarp_pathbuild_job >* ctx =
new AsyncPathKeyExchangeContext< llarp_pathbuild_job >(
&job->router->crypto);
ctx->pathset = job->context;
auto path = new llarp::path::Path(&job->hops);
path->SetBuildResultHook(std::bind(&llarp::path::PathSet::HandlePathBuilt,
ctx->pathset, std::placeholders::_1));
ctx->AsyncGenerateKeys(path, job->router->logic, job->router->tp, job,
&pathbuilder_generated_keys);
}
} // namespace llarp
llarp_pathbuilder_context::llarp_pathbuilder_context(
llarp_router* p_router, struct llarp_dht_context* p_dht, size_t pathNum,
size_t hops)
: llarp::path::PathSet(pathNum), router(p_router), dht(p_dht), numHops(hops)
{
p_router->paths.AddPathBuilder(this);
p_router->crypto.encryption_keygen(enckey);
}
llarp_pathbuilder_context::~llarp_pathbuilder_context()
{
router->paths.RemovePathBuilder(this);
}
bool
llarp_pathbuilder_context::SelectHop(llarp_nodedb* db, llarp_rc* prev,
llarp_rc* cur, size_t hop)
{
if(hop == 0)
{
return router->GetRandomConnectedRouter(cur);
}
else
llarp_nodedb_select_random_hop(db, prev, cur, hop);
return true;
}
byte_t*
llarp_pathbuilder_context::GetTunnelEncryptionSecretKey()
{
return enckey;
}
Builder::~Builder()
{
router->paths.RemovePathBuilder(this);
}
bool
llarp_pathbuilder_context::ShouldBuildMore() const
{
return llarp::path::PathSet::ShouldBuildMore()
|| router->NumberOfConnectedRouters() == 0;
}
bool
Builder::SelectHop(llarp_nodedb* db, const RouterContact& prev,
RouterContact& cur, size_t hop)
{
if(hop == 0)
{
if(router->NumberOfConnectedRouters())
return router->GetRandomConnectedRouter(cur);
else
{
llarp_nodedb_select_random_hop(db, prev, cur, 0);
return true;
}
}
else
llarp_nodedb_select_random_hop(db, prev, cur, hop);
return true;
}
void
llarp_pathbuilder_context::BuildOne()
{
llarp_pathbuild_job* job = new llarp_pathbuild_job;
job->context = this;
job->selectHop = &PathSet::SelectHopCallback;
job->hops.numHops = numHops;
job->user = this;
job->pathBuildStarted = [](llarp_pathbuild_job* j) { delete j; };
llarp_pathbuilder_build_path(job);
}
const byte_t*
Builder::GetTunnelEncryptionSecretKey() const
{
return enckey;
}
void
llarp_pathbuilder_context::ManualRebuild(size_t num)
{
llarp::LogDebug("manual rebuild ", num);
while(num--)
BuildOne();
}
bool
Builder::ShouldBuildMore() const
{
return llarp::path::PathSet::ShouldBuildMore()
|| router->NumberOfConnectedRouters() == 0;
}
struct llarp_pathbuilder_context*
llarp_pathbuilder_context_new(struct llarp_router* router,
struct llarp_dht_context* dht, size_t sz,
size_t hops)
{
return new llarp_pathbuilder_context(router, dht, sz, hops);
}
void
Builder::BuildOne()
{
// select hops
std::vector< RouterContact > hops(numHops);
size_t idx = 0;
RouterContact prev;
while(idx < numHops)
{
if(idx == 0)
{
if(!SelectHop(router->nodedb, hops[0], hops[0], 0))
{
llarp::LogError("failed to select first hop");
return;
}
}
else
{
if(!SelectHop(router->nodedb, hops[idx - 1], hops[idx], idx))
{
/// TODO: handle this failure properly
llarp::LogWarn("Failed to select hop ", idx);
return;
}
}
++idx;
}
// async generate keys
AsyncPathKeyExchangeContext< Builder >* ctx =
new AsyncPathKeyExchangeContext< Builder >(&router->crypto);
ctx->pathset = this;
auto path = new llarp::path::Path(hops);
path->SetBuildResultHook(std::bind(&llarp::path::PathSet::HandlePathBuilt,
ctx->pathset, std::placeholders::_1));
ctx->AsyncGenerateKeys(path, router->logic, router->tp, this,
&pathbuilder_generated_keys);
}
void
llarp_pathbuilder_context_free(struct llarp_pathbuilder_context* ctx)
{
delete ctx;
}
void
Builder::ManualRebuild(size_t num)
{
llarp::LogDebug("manual rebuild ", num);
while(num--)
BuildOne();
}
void
llarp_pathbuilder_build_path(struct llarp_pathbuild_job* job)
{
if(!job->context)
{
llarp::LogError("failed to build path because no context is set in job");
return;
}
if(job->selectHop == nullptr)
{
llarp::LogError("No callback provided for hop selection");
return;
}
job->router = job->context->router;
llarp_logic_queue_job(job->router->logic,
{job, &llarp::pathbuilder_start_build});
}
} // namespace path
} // namespace llarp

@ -16,7 +16,7 @@ namespace llarp
{
if(llarp_buffer_eq(key, "c"))
{
return BEncodeReadList(frames, buf);
return BEncodeReadArray(frames, buf);
}
bool read = false;
if(!BEncodeMaybeReadVersion("v", version, LLARP_PROTO_VERSION, read, key,
@ -35,7 +35,7 @@ namespace llarp
if(!BEncodeWriteDictMsgType(buf, "a", "c"))
return false;
// frames
if(!BEncodeWriteDictList("c", frames, buf))
if(!BEncodeWriteDictArray("c", frames, buf))
return false;
// version
if(!bencode_write_version_entry(buf))
@ -165,7 +165,7 @@ namespace llarp
typedef llarp::path::TransitHop Hop;
typedef AsyncFrameDecrypter< LRCMFrameDecrypt > Decrypter;
Decrypter* decrypter;
std::deque< EncryptedFrame > frames;
std::array< EncryptedFrame, 8 > frames;
Context* context;
// decrypted record
LR_CommitRecord record;
@ -174,10 +174,8 @@ namespace llarp
LRCMFrameDecrypt(Context* ctx, Decrypter* dec,
const LR_CommitMessage* commit)
: decrypter(dec), context(ctx), hop(new Hop())
: decrypter(dec), frames(commit->frames), context(ctx), hop(new Hop())
{
for(const auto& f : commit->frames)
frames.push_back(f);
hop->info.downstream = commit->remote;
}
@ -281,14 +279,21 @@ namespace llarp
llarp::LogDebug("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();
size_t sz = self->frames[0].size();
// shift
std::array< EncryptedFrame, 8 > frames;
frames[0] = self->frames[1];
frames[1] = self->frames[2];
frames[2] = self->frames[3];
frames[3] = self->frames[4];
frames[4] = self->frames[5];
frames[5] = self->frames[6];
frames[6] = self->frames[7];
// put our response on the end
self->frames.emplace_back(sz - EncryptedFrame::OverheadSize);
frames[7] = EncryptedFrame(sz - EncryptedFrame::OverheadSize);
// random junk for now
self->frames.back().Randomize();
frames[7].Randomize();
self->frames = std::move(frames);
if(self->context->HopIsUs(info.upstream))
{
// we are the farthest hop
@ -315,7 +320,7 @@ namespace llarp
LRCMFrameDecrypt* frames = new LRCMFrameDecrypt(context, decrypter, this);
// decrypt frames async
decrypter->AsyncDecrypt(context->Worker(), &frames->frames.front(), frames);
decrypter->AsyncDecrypt(context->Worker(), &frames->frames[0], frames);
return true;
}
} // namespace llarp

@ -28,6 +28,47 @@ namespace llarp
} // namespace llarp
bool
llarp_router_try_connect(struct llarp_router *router,
const llarp::RouterContact &remote,
uint16_t numretries)
{
// do we already have a pending job for this remote?
if(router->HasPendingConnectJob(remote.pubkey))
{
llarp::LogDebug("We have pending connect jobs to ", remote.pubkey);
return false;
}
// try first address only
if(remote.addrs.size())
{
auto link = router->outboundLink;
auto itr = router->pendingEstablishJobs.insert(
std::make_pair(remote.pubkey, llarp_link_establish_job()));
auto job = &itr.first->second;
job->ai = remote.addrs.front();
job->pubkey = remote.pubkey;
job->retries = numretries;
job->timeout = 10000;
job->result = &llarp_router::on_try_connect_result;
// give router as user pointer
job->user = router;
job->link = link;
// try establishing async
llarp_logic_queue_job(router->logic,
{job, [](void *u) {
llarp_link_establish_job *j =
static_cast< llarp_link_establish_job * >(u);
j->link->try_establish(j);
j->link = nullptr;
}});
return true;
}
llarp::LogWarn("couldn't get first address for ", remote.pubkey);
return false;
}
llarp_router::llarp_router()
: ready(false)
, paths(this)
@ -39,13 +80,11 @@ llarp_router::llarp_router()
// set rational defaults
this->ip4addr.sin_family = AF_INET;
this->ip4addr.sin_port = htons(1090);
llarp_rc_clear(&rc);
}
llarp_router::~llarp_router()
{
llarp_dht_context_free(dht);
llarp_rc_free(&rc);
}
bool
@ -104,8 +143,7 @@ llarp_router::SendToOrQueue(const llarp::RouterID &remote,
outboundMessageQueue[remote].push(std::move(msg));
// we don't have an open session to that router right now
auto rc = llarp_nodedb_get_rc(nodedb, remote);
if(rc)
if(llarp_nodedb_get_rc(nodedb, remote, rc))
{
// try connecting directly as the rc is loaded from disk
llarp_router_try_connect(this, rc, 10);
@ -113,55 +151,45 @@ llarp_router::SendToOrQueue(const llarp::RouterID &remote,
}
// we don't have the RC locally so do a dht lookup
llarp_router_lookup_job *lookup = new llarp_router_lookup_job();
lookup->user = this;
lookup->iterative = false;
llarp_rc_clear(&lookup->result);
memcpy(lookup->target, remote, PUBKEYSIZE);
lookup->hook = &llarp_router::HandleDHTLookupForSendTo;
lookup->user = this;
llarp_dht_lookup_router(dht, lookup);
dht->impl.LookupRouter(remote,
std::bind(&llarp_router::HandleDHTLookupForSendTo,
this, remote, std::placeholders::_1));
return true;
}
void
llarp_router::HandleDHTLookupForSendTo(llarp_router_lookup_job *job)
llarp_router::HandleDHTLookupForSendTo(
llarp::RouterID remote, const std::vector< llarp::RouterContact > &results)
{
llarp_router *self = static_cast< llarp_router * >(job->user);
if(job->found)
if(results.size())
{
llarp_nodedb_put_rc(self->nodedb, &job->result);
llarp_router_try_connect(self, &job->result, 10);
llarp_rc_free(&job->result);
llarp_nodedb_put_rc(nodedb, results[0]);
llarp_router_try_connect(this, results[0], 10);
}
else
{
self->DiscardOutboundFor(job->target);
DiscardOutboundFor(remote);
}
delete job;
}
void
llarp_router::try_connect(fs::path rcfile)
{
llarp_rc remote;
llarp_rc_new(&remote);
if(!llarp_rc_read(rcfile.string().c_str(), &remote))
llarp::RouterContact remote;
if(!remote.Read(rcfile.string().c_str()))
{
llarp::LogError("failure to decode or verify of remote RC");
return;
}
if(llarp_rc_verify_sig(&crypto, &remote))
if(remote.VerifySignature(&crypto))
{
llarp::LogDebug("verified signature");
// store into filesystem
// TODO: should this be async?
if(!llarp_nodedb_put_rc(nodedb, &remote))
if(!llarp_nodedb_put_rc(nodedb, remote))
{
llarp::LogWarn("failed to store");
}
if(!llarp_router_try_connect(this, &remote, 10))
if(!llarp_router_try_connect(this, remote, 10))
{
// or error?
llarp::LogWarn("session already made");
@ -169,7 +197,6 @@ llarp_router::try_connect(fs::path rcfile)
}
else
llarp::LogError("failed to verify signature of RC", rcfile);
llarp_rc_free(&remote);
}
bool
@ -185,7 +212,7 @@ bool
llarp_router::EnsureEncryptionKey()
{
return llarp_findOrCreateEncryption(
&crypto, encryption_keyfile.string().c_str(), &this->encryption);
&crypto, encryption_keyfile.string().c_str(), encryption);
}
void
@ -204,7 +231,7 @@ bool
llarp_router::SaveRC()
{
llarp::LogDebug("verify RC signature");
if(!llarp_rc_verify_sig(&crypto, &rc))
if(!rc.VerifySignature(&crypto))
{
llarp::LogError("RC has bad signature not saving");
return false;
@ -213,7 +240,7 @@ llarp_router::SaveRC()
byte_t tmp[MAX_RC_SIZE];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
if(llarp_rc_bencode(&rc, &buf))
if(rc.BEncode(&buf))
{
std::ofstream f(our_rc_file.string());
@ -272,9 +299,7 @@ llarp_router::on_verify_client_rc(llarp_async_verify_rc *job)
{
llarp::async_verify_context *ctx =
static_cast< llarp::async_verify_context * >(job->user);
llarp::PubKey pk = job->rc.pubkey;
llarp_rc_free(&job->rc);
ctx->router->pendingEstablishJobs.erase(pk);
ctx->router->pendingEstablishJobs.erase(job->rc.pubkey);
delete ctx;
}
@ -295,7 +320,6 @@ llarp_router::on_verify_server_rc(llarp_async_verify_rc *job)
if(session)
session->close();
}
llarp_rc_free(&job->rc);
router->pendingEstablishJobs.erase(pk);
router->DiscardOutboundFor(pk);
return;
@ -305,16 +329,10 @@ llarp_router::on_verify_server_rc(llarp_async_verify_rc *job)
llarp::LogDebug("rc verified and saved to nodedb");
// refresh valid routers RC value if it's there
auto v = router->validRouters.find(pk);
if(v != router->validRouters.end())
{
// free previous RC members
llarp_rc_free(&v->second);
}
router->validRouters[pk] = job->rc;
// track valid router in dht
__llarp_dht_put_peer(router->dht, &router->validRouters[pk]);
router->dht->impl.nodes->PutNode(job->rc);
// this was an outbound establish job
if(ctx->establish_job)
@ -342,42 +360,31 @@ llarp_router::handle_router_ticker(void *user, uint64_t orig, uint64_t left)
void
llarp_router::TryEstablishTo(const llarp::RouterID &remote)
{
auto rc = llarp_nodedb_get_rc(nodedb, remote);
if(rc)
llarp::RouterContact rc;
if(llarp_nodedb_get_rc(nodedb, remote, rc))
{
// try connecting
// try connecting async
llarp_router_try_connect(this, rc, 5);
}
else
{
// dht lookup as we don't know it
llarp_router_lookup_job *lookup = new llarp_router_lookup_job;
llarp_rc_clear(&lookup->result);
memcpy(lookup->target, remote, PUBKEYSIZE);
lookup->hook = &llarp_router::HandleDHTLookupForTryEstablishTo;
lookup->iterative = false;
lookup->user = this;
llarp_dht_lookup_router(dht, lookup);
dht->impl.LookupRouter(
remote,
std::bind(&llarp_router::HandleDHTLookupForTryEstablishTo, this,
std::placeholders::_1));
}
}
void
llarp_router::HandleDHTLookupForTryEstablishTo(llarp_router_lookup_job *job)
llarp_router::HandleDHTLookupForTryEstablishTo(
const std::vector< llarp::RouterContact > &results)
{
if(job->found)
if(results.size())
{
llarp_router *self = static_cast< llarp_router * >(job->user);
llarp_nodedb_put_rc(self->nodedb, &job->result);
llarp_router_try_connect(self, &job->result, 5);
llarp_rc_free(&job->result);
llarp_nodedb_put_rc(nodedb, results[0]);
llarp_router_try_connect(this, results[0], 5);
}
delete job;
}
void
llarp_router::HandleExploritoryPathBuildStarted(llarp_pathbuild_job *job)
{
delete job;
}
size_t
@ -487,9 +494,7 @@ llarp_router::SessionClosed(const llarp::RouterID &remote)
auto itr = validRouters.find(remote);
if(itr == validRouters.end())
return;
__llarp_dht_remove_peer(dht, remote);
llarp_rc_free(&itr->second);
validRouters.erase(itr);
}
@ -585,7 +590,7 @@ llarp_router::DiscardOutboundFor(const llarp::RouterID &remote)
}
bool
llarp_router::GetRandomConnectedRouter(llarp_rc *result) const
llarp_router::GetRandomConnectedRouter(llarp::RouterContact &result) const
{
auto sz = validRouters.size();
if(sz)
@ -593,21 +598,25 @@ llarp_router::GetRandomConnectedRouter(llarp_rc *result) const
auto itr = validRouters.begin();
if(sz > 1)
std::advance(itr, llarp_randint() % sz);
llarp_rc_copy(result, &itr->second);
result = itr->second;
return true;
}
return false;
}
void
llarp_router::async_verify_RC(llarp_rc *rc, bool isExpectingClient,
llarp_router::async_verify_RC(const llarp::RouterContact &rc,
bool isExpectingClient,
llarp_link_establish_job *establish_job)
{
llarp_async_verify_rc *job = new llarp_async_verify_rc();
job->user = new llarp::async_verify_context{this, establish_job};
job->rc = {};
job->valid = false;
job->hook = nullptr;
llarp_async_verify_rc *job = new llarp_async_verify_rc();
llarp::async_verify_context *ctx = new llarp::async_verify_context();
ctx->router = this;
ctx->establish_job = establish_job;
job->user = ctx;
job->rc = rc;
job->valid = false;
job->hook = nullptr;
job->nodedb = nodedb;
job->logic = logic;
@ -615,7 +624,6 @@ llarp_router::async_verify_RC(llarp_rc *rc, bool isExpectingClient,
job->cryptoworker = tp;
job->diskworker = disk;
llarp_rc_copy(&job->rc, rc);
if(isExpectingClient)
job->hook = &llarp_router::on_verify_client_rc;
else
@ -627,10 +635,6 @@ void
llarp_router::Run()
{
// zero out router contact
llarp::Zero(&rc, sizeof(llarp_rc));
// fill our address list
rc.addrs = llarp_ai_list_new();
sockaddr *dest = (sockaddr *)&this->ip4addr;
llarp::Addr publicAddr(*dest);
if(this->publicOverride)
@ -644,8 +648,8 @@ llarp_router::Run()
llarp::LogInfo("You have ", inboundLinks.size(), " inbound links");
for(auto link : inboundLinks)
{
llarp_ai addr;
link->get_our_address(&addr);
llarp::AddressInfo addr;
link->get_our_address(addr);
llarp::Addr a(addr);
if(this->publicOverride && a.sameAddr(publicAddr))
{
@ -654,7 +658,7 @@ llarp_router::Run()
if(!a.isPrivate())
{
llarp::LogInfo("Loading Addr: ", a, " into our RC");
llarp_ai_list_pushback(rc.addrs, &addr);
rc.addrs.push_back(addr);
}
};
if(this->publicOverride)
@ -674,47 +678,27 @@ llarp_router::Run()
return;
}
link = inboundLinks.front();
/*
// create a new link
link = new llarp_link;
llarp::Zero(link, sizeof(llarp_link));
llarp_iwp_args args = {
.crypto = &this->crypto,
.logic = this->logic,
.cryptoworker = this->tp,
.router = this,
.keyfile = this->transport_keyfile.c_str(),
};
iwp_link_init(link, args);
if(llarp_link_initialized(link))
{
}
*/
}
link->get_our_address(&this->addrInfo);
link->get_our_address(this->addrInfo);
// override ip and port
this->addrInfo.ip = *publicAddr.addr6();
this->addrInfo.port = publicAddr.port();
llarp::LogInfo("Loaded our public ", publicAddr, " override into RC!");
// we need the link to set the pubkey
llarp_ai_list_pushback(rc.addrs, &this->addrInfo);
rc.addrs.push_back(this->addrInfo);
}
// set public encryption key
llarp_rc_set_pubenckey(&rc, llarp::seckey_topublic(encryption));
char ftmp[68] = {0};
const char *hexKey = llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(
llarp::seckey_topublic(encryption), ftmp);
llarp::LogInfo("Your Encryption pubkey ", hexKey);
rc.enckey = llarp::seckey_topublic(encryption);
llarp::LogInfo("Your Encryption pubkey ", rc.enckey);
// set public signing key
llarp_rc_set_pubsigkey(&rc, llarp::seckey_topublic(identity));
hexKey = llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(
llarp::seckey_topublic(identity), ftmp);
llarp::LogInfo("Your Identity pubkey ", hexKey);
rc.pubkey = llarp::seckey_topublic(identity);
llarp::LogInfo("Your Identity pubkey ", rc.pubkey);
llarp_rc_sign(&crypto, identity, &rc);
if(!rc.Sign(&crypto, identity))
{
llarp::LogError("failed to sign rc");
return;
}
if(!SaveRC())
{
@ -865,166 +849,6 @@ llarp_run_router(struct llarp_router *router, struct llarp_nodedb *nodedb)
router->Run();
}
bool
llarp_router_try_connect(struct llarp_router *router, struct llarp_rc *remote,
uint16_t numretries)
{
char ftmp[68] = {0};
const char *hexname =
llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(remote->pubkey, ftmp);
// do we already have a pending job for this remote?
if(router->HasPendingConnectJob(remote->pubkey))
{
llarp::LogDebug("We have pending connect jobs to ", hexname);
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.insert(
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(job);
return true;
}
llarp::LogWarn("couldn't get first address for ", hexname);
return false;
}
void
llarp_rc_clear(struct llarp_rc *rc)
{
// zero out router contact
llarp::Zero(rc, sizeof(llarp_rc));
}
void
llarp_rc_set_pubenckey(struct llarp_rc *rc, const uint8_t *pubenckey)
{
// set public encryption key
memcpy(rc->enckey, pubenckey, PUBKEYSIZE);
}
void
llarp_rc_set_pubsigkey(struct llarp_rc *rc, const uint8_t *pubsigkey)
{
// set public signing key
memcpy(rc->pubkey, pubsigkey, PUBKEYSIZE);
}
void
llarp_rc_set_pubkey(struct llarp_rc *rc, const uint8_t *pubenckey,
const uint8_t *pubsigkey)
{
// set public encryption key
llarp_rc_set_pubenckey(rc, pubenckey);
// set public signing key
llarp_rc_set_pubsigkey(rc, pubsigkey);
}
bool
llarp_rc_read(const char *fpath, llarp_rc *result)
{
fs::path our_rc_file(fpath);
std::error_code ec;
if(!fs::exists(our_rc_file, ec))
{
printf("File[%s] not found\n", fpath);
return false;
}
std::ifstream f(our_rc_file.string(), std::ios::binary);
if(!f.is_open())
{
printf("Can't open file [%s]\n", fpath);
return false;
}
byte_t tmp[MAX_RC_SIZE];
llarp_buffer_t buf = llarp::StackBuffer< decltype(tmp) >(tmp);
f.seekg(0, std::ios::end);
size_t sz = f.tellg();
f.seekg(0, std::ios::beg);
if(sz > buf.sz)
return false;
f.read((char *)buf.base, sz);
// printf("contents[%s]\n", tmpc);
llarp::Zero(result, sizeof(llarp_rc));
if(!llarp_rc_bdecode(result, &buf))
{
llarp::LogError("Can't decode ", fpath);
return false;
}
return true;
}
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);
}
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.string(), 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)
{
@ -1052,14 +876,6 @@ llarp_free_router(struct llarp_router **router)
*router = nullptr;
}
void
llarp_router_override_path_selection(struct llarp_router *router,
llarp_pathbuilder_select_hop_func func)
{
if(func)
router->selectHopFunc = func;
}
bool
llarp_findOrCreateIdentity(llarp_crypto *crypto, const char *fpath,
byte_t *secretkey)
@ -1226,13 +1042,9 @@ namespace llarp
{
if(StrEq(key, "nickname"))
{
if(llarp_rc_set_nickname(&self->rc, val))
{
// set logger name here
_glog.nodeName = self->rc.Nick();
}
else
llarp::LogWarn("failed to set nickname to ", val);
self->rc.SetNick(val);
// set logger name here
_glog.nodeName = self->rc.Nick();
}
if(StrEq(key, "encryption-privkey"))
{

@ -1,8 +1,8 @@
#ifndef LLARP_ROUTER_HPP
#define LLARP_ROUTER_HPP
#include <llarp/dht.h>
#include <llarp/nodedb.h>
#include <llarp/router_contact.h>
#include <llarp/nodedb.hpp>
#include <llarp/router_contact.hpp>
#include <llarp/path.hpp>
#include <functional>
@ -24,25 +24,12 @@
/** 2^15 bytes */
#define MAX_LINK_MSG_SIZE (32768)
// TODO: unused. remove?
// struct try_connect_ctx
// {
// llarp_router *router = nullptr;
// llarp_ai addr;
// };
// // forward declare
// namespace path
// {
// struct TransitHop;
// }
struct llarp_link;
struct llarp_link_session_iter;
bool
llarp_findOrCreateEncryption(llarp_crypto *crypto, const char *fpath,
llarp::SecretKey *encryption);
llarp::SecretKey &encryption);
struct llarp_router
{
@ -62,12 +49,12 @@ struct llarp_router
fs::path our_rc_file = "rc.signed";
// our router contact
llarp_rc rc;
llarp::RouterContact rc;
// our ipv4 public setting
bool publicOverride = false;
struct sockaddr_in ip4addr;
llarp_ai addrInfo;
llarp::AddressInfo addrInfo;
llarp_ev_loop *netloop;
llarp_threadpool *tp;
@ -92,9 +79,6 @@ struct llarp_router
llarp::InboundMessageParser inbound_link_msg_parser;
llarp::routing::InboundMessageParser inbound_routing_msg_parser;
llarp_pathbuilder_select_hop_func selectHopFunc = nullptr;
llarp_pathbuilder_context *explorePool = nullptr;
llarp::service::Context hiddenServiceContext;
llarp_link *outboundLink = nullptr;
@ -107,7 +91,7 @@ struct llarp_router
std::map< llarp::RouterID, MessageQueue > outboundMessageQueue;
/// loki verified routers
std::map< llarp::RouterID, llarp_rc > validRouters;
std::map< llarp::RouterID, llarp::RouterContact > validRouters;
// pending establishing session with routers
std::map< llarp::PubKey, llarp_link_establish_job > pendingEstablishJobs;
@ -222,12 +206,20 @@ struct llarp_router
NumberOfConnectedRouters() const;
bool
GetRandomConnectedRouter(llarp_rc *result) const;
GetRandomConnectedRouter(llarp::RouterContact &result) const;
void
async_verify_RC(llarp_rc *rc, bool isExpectingClient,
async_verify_RC(const llarp::RouterContact &rc, bool isExpectingClient,
llarp_link_establish_job *job = nullptr);
void
HandleDHTLookupForSendTo(llarp::RouterID remote,
const std::vector< llarp::RouterContact > &results);
void
HandleDHTLookupForTryEstablishTo(
const std::vector< llarp::RouterContact > &results);
static bool
iter_try_connect(llarp_router_link_iter *i, llarp_router *router,
llarp_link *l);
@ -253,15 +245,6 @@ struct llarp_router
static void
HandleAsyncLoadRCForSendTo(llarp_async_load_rc *async);
static void
HandleDHTLookupForSendTo(llarp_router_lookup_job *job);
static void
HandleExploritoryPathBuildStarted(llarp_pathbuild_job *job);
static void
HandleDHTLookupForTryEstablishTo(llarp_router_lookup_job *job);
};
#endif

@ -1,264 +1,98 @@
#include <llarp/bencode.h>
#include <llarp/router_contact.h>
#include <llarp/bencode.hpp>
#include <llarp/router_contact.hpp>
#include <llarp/version.h>
#include <llarp/crypto.hpp>
#include "buffer.hpp"
#include "logger.hpp"
#include "mem.hpp"
bool
llarp_rc_new(struct llarp_rc *rc)
namespace llarp
{
rc->addrs = llarp_ai_list_new();
rc->exits = llarp_xi_list_new();
rc->last_updated = 0;
llarp::Zero(rc->nickname, sizeof(rc->nickname));
return true;
}
void
llarp_rc_free(struct llarp_rc *rc)
{
if(rc->exits)
llarp_xi_list_free(rc->exits);
if(rc->addrs)
llarp_ai_list_free(rc->addrs);
rc->exits = 0;
rc->addrs = 0;
}
struct llarp_rc_decoder
{
struct llarp_rc *rc;
struct llarp_alloc *mem;
};
static bool
llarp_rc_decode_dict(struct dict_reader *r, llarp_buffer_t *key)
{
uint64_t v;
llarp_buffer_t strbuf;
llarp_rc *rc = static_cast< llarp_rc * >(r->user);
if(!key)
return true;
if(llarp_buffer_eq(*key, "a"))
bool
RouterContact::BEncode(llarp_buffer_t *buf) const
{
if(rc->addrs)
{
llarp_ai_list_free(rc->addrs);
}
rc->addrs = llarp_ai_list_new();
return llarp_ai_list_bdecode(rc->addrs, r->buffer);
}
if(llarp_buffer_eq(*key, "k"))
{
if(!bencode_read_string(r->buffer, &strbuf))
/* write dict begin */
if(!bencode_start_dict(buf))
return false;
if(strbuf.sz != PUBKEYSIZE)
return false;
memcpy(rc->pubkey, strbuf.base, PUBKEYSIZE);
return true;
}
if(llarp_buffer_eq(*key, "n"))
{
if(!bencode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz > sizeof(rc->nickname))
return false;
llarp::Zero(rc->nickname, sizeof(rc->nickname));
memcpy(rc->nickname, strbuf.base, strbuf.sz);
return true;
}
if(llarp_buffer_eq(*key, "p"))
{
if(!bencode_read_string(r->buffer, &strbuf))
/* write ai if they exist */
if(!bencode_write_bytestring(buf, "a", 1))
return false;
if(strbuf.sz != PUBKEYSIZE)
if(!BEncodeWriteList(addrs.begin(), addrs.end(), buf))
return false;
memcpy(rc->enckey, strbuf.base, PUBKEYSIZE);
return true;
}
if(llarp_buffer_eq(*key, "u"))
{
if(!bencode_read_integer(r->buffer, &rc->last_updated))
/* write signing pubkey */
if(!bencode_write_bytestring(buf, "k", 1))
return false;
return true;
}
if(llarp_buffer_eq(*key, "v"))
{
if(!bencode_read_integer(r->buffer, &v))
if(!pubkey.BEncode(buf))
return false;
return v == LLARP_PROTO_VERSION;
}
if(llarp_buffer_eq(*key, "x"))
{
if(rc->exits)
std::string nick = Nick();
if(nick.size())
{
llarp_xi_list_free(rc->exits);
/* write nickname */
if(!bencode_write_bytestring(buf, "n", 1))
return false;
if(!bencode_write_bytestring(buf, nick.c_str(), nick.size()))
return false;
}
rc->exits = llarp_xi_list_new();
return llarp_xi_list_bdecode(rc->exits, r->buffer);
}
if(llarp_buffer_eq(*key, "z"))
{
if(!bencode_read_string(r->buffer, &strbuf))
/* write encryption pubkey */
if(!bencode_write_bytestring(buf, "p", 1))
return false;
if(strbuf.sz != SIGSIZE)
if(!enckey.BEncode(buf))
return false;
memcpy(rc->signature, strbuf.base, SIGSIZE);
return true;
}
return false;
}
bool
llarp_rc_is_public_router(const struct llarp_rc *const rc)
{
return rc->addrs && llarp_ai_list_size(rc->addrs) > 0;
}
bool
llarp_rc_set_nickname(struct llarp_rc *rc, const char *nick)
{
strncpy((char *)rc->nickname, nick, sizeof(rc->nickname));
/// TODO: report nickname truncation
return true;
}
void
llarp_rc_copy(struct llarp_rc *dst, const struct llarp_rc *src)
{
llarp_rc_free(dst);
llarp_rc_clear(dst);
memcpy(dst->pubkey, src->pubkey, PUBKEYSIZE);
memcpy(dst->enckey, src->enckey, PUBKEYSIZE);
memcpy(dst->signature, src->signature, SIGSIZE);
dst->last_updated = src->last_updated;
if(src->addrs)
{
dst->addrs = llarp_ai_list_new();
llarp_ai_list_copy(dst->addrs, src->addrs);
}
if(src->exits)
{
dst->exits = llarp_xi_list_new();
llarp_xi_list_copy(dst->exits, src->exits);
}
memcpy(dst->nickname, src->nickname, sizeof(dst->nickname));
}
bool
llarp_rc_bdecode(struct llarp_rc *rc, llarp_buffer_t *buff)
{
dict_reader r = {buff, rc, &llarp_rc_decode_dict};
return bencode_read_dict(buff, &r);
}
bool
llarp_rc_verify_sig(struct llarp_crypto *crypto, struct llarp_rc *rc)
{
// maybe we should copy rc before modifying it
// would that make it more thread safe?
// jeff agrees
bool result = false;
llarp::Signature sig;
byte_t tmp[MAX_RC_SIZE];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
// copy sig
memcpy(sig, rc->signature, SIGSIZE);
// zero sig
size_t sz = 0;
while(sz < SIGSIZE)
rc->signature[sz++] = 0;
// bencode
if(llarp_rc_bencode(rc, &buf))
{
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
result = crypto->verify(rc->pubkey, buf, sig);
}
else
llarp::LogWarn("RC encode failed");
// restore sig
memcpy(rc->signature, sig, SIGSIZE);
return result;
}
/* write last updated */
if(!bencode_write_bytestring(buf, "u", 1))
return false;
if(!bencode_write_uint64(buf, last_updated))
return false;
bool
llarp_rc_bencode(const struct llarp_rc *rc, llarp_buffer_t *buff)
{
/* write dict begin */
if(!bencode_start_dict(buff))
return false;
/* write version */
if(!bencode_write_version_entry(buf))
return false;
if(rc->addrs)
{
/* write ai if they exist */
if(!bencode_write_bytestring(buff, "a", 1))
if(!bencode_write_bytestring(buf, "x", 1))
return false;
if(!llarp_ai_list_bencode(rc->addrs, buff))
if(!BEncodeWriteList(exits.begin(), exits.end(), buf))
return false;
}
/* write signing pubkey */
if(!bencode_write_bytestring(buff, "k", 1))
return false;
if(!bencode_write_bytestring(buff, rc->pubkey, PUBKEYSIZE))
return false;
/* write signature */
if(!bencode_write_bytestring(buf, "z", 1))
return false;
if(!signature.BEncode(buf))
return false;
return bencode_end(buf);
}
auto nicklen = strnlen((char *)rc->nickname, sizeof(rc->nickname));
if(nicklen)
bool
RouterContact::DecodeKey(llarp_buffer_t key, llarp_buffer_t *buf)
{
/* write nickname */
if(!bencode_write_bytestring(buff, "n", 1))
bool read = false;
if(!BEncodeMaybeReadDictList("a", addrs, read, key, buf))
return false;
if(!bencode_write_bytestring(buff, rc->nickname, nicklen))
if(!BEncodeMaybeReadDictEntry("k", pubkey, read, key, buf))
return false;
}
/* write encryption pubkey */
if(!bencode_write_bytestring(buff, "p", 1))
return false;
if(!bencode_write_bytestring(buff, rc->enckey, PUBKEYSIZE))
return false;
if(!BEncodeMaybeReadDictEntry("n", nickname, read, key, buf))
return false;
/* write last updated */
if(!bencode_write_bytestring(buff, "u", 1))
return false;
if(!bencode_write_uint64(buff, rc->last_updated))
return false;
if(!BEncodeMaybeReadDictEntry("p", enckey, read, key, buf))
return false;
/* write version */
if(!bencode_write_version_entry(buff))
return false;
if(!BEncodeMaybeReadDictInt("u", last_updated, read, key, buf))
return false;
if(rc->exits)
{
/* write ai if they exist */
if(!bencode_write_bytestring(buff, "x", 1))
if(!BEncodeMaybeReadDictList("x", exits, read, key, buf))
return false;
if(!llarp_xi_list_bencode(rc->exits, buff))
if(!BEncodeMaybeReadDictEntry("z", signature, read, key, buf))
return false;
return read;
}
/* write signature */
if(!bencode_write_bytestring(buff, "z", 1))
return false;
if(!bencode_write_bytestring(buff, rc->signature, SIGSIZE))
return false;
return bencode_end(buff);
}
} // namespace llarp

@ -1,5 +0,0 @@
#ifndef LLARP_RC_HPP
#define LLARP_RC_HPP
#include <llarp/router_contact.h>
#endif

@ -11,7 +11,7 @@ namespace llarp
namespace service
{
Endpoint::Endpoint(const std::string& name, llarp_router* r)
: llarp_pathbuilder_context(r, r->dht, 2, 4), m_Router(r), m_Name(name)
: path::Builder(r, r->dht, 2, 4), m_Router(r), m_Name(name)
{
m_Tag.Zero();
}
@ -594,8 +594,7 @@ namespace llarp
job->diskworker = m_Router->disk;
job->logic = nullptr;
job->hook = nullptr;
llarp_rc_clear(&job->rc);
llarp_rc_copy(&job->rc, &msg->R[0]);
job->rc = msg->R[0];
llarp_nodedb_async_verify(job);
return true;
}
@ -607,7 +606,8 @@ namespace llarp
{
if(router.IsZero())
return;
if(!llarp_nodedb_get_rc(m_Router->nodedb, router))
RouterContact rc;
if(!llarp_nodedb_get_rc(m_Router->nodedb, router, rc))
{
if(m_PendingRouters.find(router) == m_PendingRouters.end())
{
@ -712,8 +712,7 @@ namespace llarp
Endpoint::OutboundContext::OutboundContext(const IntroSet& intro,
Endpoint* parent)
: llarp_pathbuilder_context(parent->m_Router, parent->m_Router->dht, 2,
4)
: path::Builder(parent->m_Router, parent->m_Router->dht, 2, 4)
, currentIntroSet(intro)
, m_Parent(parent)
@ -976,15 +975,14 @@ namespace llarp
}
bool
Endpoint::OutboundContext::SelectHop(llarp_nodedb* db, llarp_rc* prev,
llarp_rc* cur, size_t hop)
Endpoint::OutboundContext::SelectHop(llarp_nodedb* db,
const RouterContact& prev,
RouterContact& cur, size_t hop)
{
if(hop == numHops - 1)
{
auto localcopy = llarp_nodedb_get_rc(db, selectedIntro.router);
if(localcopy)
if(llarp_nodedb_get_rc(db, selectedIntro.router, cur))
{
llarp_rc_copy(cur, localcopy);
return true;
}
else
@ -999,7 +997,7 @@ namespace llarp
}
}
else
return llarp_pathbuilder_context::SelectHop(db, prev, cur, hop);
return path::Builder::SelectHop(db, prev, cur, hop);
}
uint64_t

@ -49,7 +49,7 @@ namespace llarp
}
for(;;)
{
llarp_thread_job job;
Job_t job;
{
lock_t lock(this->queue_mutex);
this->condition.WaitUntil(
@ -59,18 +59,15 @@ namespace llarp
// discard pending jobs
while(this->jobs.size())
{
delete this->jobs.top().job;
this->jobs.pop();
}
return;
}
job.user = this->jobs.top().job->user;
job.work = this->jobs.top().job->work;
delete this->jobs.top().job;
job = std::move(this->jobs.top());
this->jobs.pop();
}
// do work
job.work(job.user);
job();
}
});
}
@ -104,8 +101,7 @@ namespace llarp
// don't allow enqueueing after stopping the pool
if(stop)
return;
jobs.emplace(ids++, new llarp_thread_job(job.user, job.work));
jobs.emplace(ids++, job);
}
condition.NotifyOne();
}
@ -197,7 +193,8 @@ struct llarp_threadpool
llarp::thread::Pool *impl;
llarp::util::Mutex m_access;
std::queue< llarp_thread_job * > jobs;
uint32_t ids = 0;
std::queue< llarp::thread::Pool::Job_t > jobs;
llarp_threadpool(int workers, const char *name, bool isolate,
setup_net_func setup = nullptr,
@ -284,15 +281,11 @@ llarp_threadpool_queue_job(struct llarp_threadpool *pool,
{
if(pool->impl)
pool->impl->QueueJob(job);
else if(job.user && job.work)
else
{
auto j = new llarp_thread_job;
j->work = job.work;
j->user = job.user;
{
llarp::util::Lock lock(pool->m_access);
pool->jobs.push(j);
}
// single threaded mode
llarp::util::Lock lock(pool->m_access);
pool->jobs.emplace(++pool->ids, job);
}
}
@ -301,14 +294,13 @@ llarp_threadpool_tick(struct llarp_threadpool *pool)
{
while(pool->jobs.size())
{
llarp_thread_job *job;
llarp::thread::Pool::Job_t job;
{
llarp::util::Lock lock(pool->m_access);
job = pool->jobs.front();
job = std::move(pool->jobs.front());
pool->jobs.pop();
}
job->work(job->user);
delete job;
job();
}
}

@ -34,8 +34,13 @@ namespace llarp
struct Job_t
{
uint32_t id;
llarp_thread_job* job;
Job_t(uint32_t jobid, llarp_thread_job* j) : id(jobid), job(j)
void* user;
llarp_thread_work_func work;
Job_t() = default;
Job_t(uint32_t jobid, const llarp_thread_job& j)
: id(jobid), user(j.user), work(j.work)
{
}
@ -44,6 +49,12 @@ namespace llarp
{
return id < j.id;
}
void
operator()() const
{
work(user);
}
};
std::priority_queue< Job_t > jobs;

@ -56,8 +56,8 @@ namespace llarp
struct llarp_timer_context
{
llarp::util::Mutex timersMutex;
std::unordered_map< uint32_t, llarp::timer* > timers;
std::priority_queue< llarp::timer* > calling;
std::unordered_map< uint32_t, std::unique_ptr< llarp::timer > > timers;
std::priority_queue< std::unique_ptr< llarp::timer > > calling;
llarp::util::Mutex tickerMutex;
llarp::util::Condition* ticker = nullptr;
std::chrono::milliseconds nextTickLen = std::chrono::milliseconds(100);
@ -87,7 +87,7 @@ struct llarp_timer_context
cancel(uint32_t id)
{
llarp::util::Lock lock(timersMutex);
auto itr = timers.find(id);
const auto& itr = timers.find(id);
if(itr == timers.end())
return;
itr->second->canceled = true;
@ -97,7 +97,7 @@ struct llarp_timer_context
remove(uint32_t id)
{
llarp::util::Lock lock(timersMutex);
auto itr = timers.find(id);
const auto& itr = timers.find(id);
if(itr == timers.end())
return;
itr->second->func = nullptr;
@ -109,7 +109,10 @@ struct llarp_timer_context
{
llarp::util::Lock lock(timersMutex);
uint32_t id = ++ids;
timers[id] = new llarp::timer(timeout_ms, user, func);
timers.insert(
std::make_pair(id,
std::unique_ptr< llarp::timer >(
new llarp::timer(timeout_ms, user, func))));
return id;
}
@ -184,24 +187,30 @@ llarp_timer_tick_all(struct llarp_timer_context* t)
if(!t->run())
return;
auto now = llarp_time_now_ms();
auto itr = t->timers.begin();
while(itr != t->timers.end())
std::list< std::unique_ptr< llarp::timer > > hit;
{
if(now - itr->second->started >= itr->second->timeout
|| itr->second->canceled)
llarp::util::Lock lock(t->timersMutex);
auto itr = t->timers.begin();
while(itr != t->timers.end())
{
if(itr->second->func && itr->second->called_at == 0)
if(now - itr->second->started >= itr->second->timeout
|| itr->second->canceled)
{
// timer hit
itr->second->called_at = now;
itr->second->exec();
llarp::timer* timer = itr->second;
itr = t->timers.erase(itr);
delete timer;
continue;
hit.emplace_back(std::move(itr->second));
itr = t->timers.erase(itr);
}
else
++itr;
}
}
for(const auto& h : hit)
{
if(h->func)
{
h->called_at = now;
h->exec();
}
++itr;
}
}

Loading…
Cancel
Save