ALMOST got path building working

pull/1/head
Jeff Becker 6 years ago
parent 50402820e1
commit 39c63432be
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -124,6 +124,7 @@ set(LIB_SRC
llarp/nodedb.cpp llarp/nodedb.cpp
llarp/path.cpp llarp/path.cpp
llarp/pathbuilder.cpp llarp/pathbuilder.cpp
llarp/path_confirm.cpp
llarp/proofofwork.cpp llarp/proofofwork.cpp
llarp/relay_ack.cpp llarp/relay_ack.cpp
llarp/relay_commit.cpp llarp/relay_commit.cpp
@ -131,6 +132,7 @@ set(LIB_SRC
llarp/router_contact.cpp llarp/router_contact.cpp
llarp/router.cpp llarp/router.cpp
llarp/threadpool.cpp llarp/threadpool.cpp
llarp/transit_hop.cpp
llarp/testnet.c llarp/testnet.c
llarp/time.cpp llarp/time.cpp
llarp/timer.cpp llarp/timer.cpp

@ -294,7 +294,8 @@ the path is extended by w.y seconds
c: "<32 byte public encryption key used for upstream>", c: "<32 byte public encryption key used for upstream>",
i: "<32 byte RC.k of next hop>", i: "<32 byte RC.k of next hop>",
n: "<32 bytes nounce for key exchange>", n: "<32 bytes nounce for key exchange>",
p: "<16 bytes path id>", r: "<16 bytes rx path id>",
t: "<16 bytes tx path id>",
v: 0, v: 0,
w: proof of work w: proof of work
} }

@ -19,6 +19,12 @@ namespace llarp
AlignedBuffer() = default; AlignedBuffer() = default;
AlignedBuffer(const AlignedBuffer& other)
{
for(size_t idx = 0; idx < (sz / 8); ++idx)
l[idx] = other.l[idx];
}
AlignedBuffer(const byte_t* data) AlignedBuffer(const byte_t* data)
{ {
for(size_t idx = 0; idx < sz; ++idx) for(size_t idx = 0; idx < sz; ++idx)

@ -12,7 +12,7 @@ namespace llarp
struct Encrypted struct Encrypted
{ {
Encrypted(Encrypted&&) = delete; Encrypted(Encrypted&&) = delete;
Encrypted();
Encrypted(const byte_t* buf, size_t sz); Encrypted(const byte_t* buf, size_t sz);
Encrypted(size_t sz); Encrypted(size_t sz);
~Encrypted(); ~Encrypted();
@ -23,6 +23,18 @@ namespace llarp
return bencode_write_bytestring(buf, _data, _sz); return bencode_write_bytestring(buf, _data, _sz);
} }
Encrypted&
operator=(llarp_buffer_t buf)
{
if(_data)
delete[] _data;
_sz = buf.sz;
_data = new byte_t[_sz];
memcpy(_data, buf.base, _sz);
UpdateBuffer();
return *this;
}
void void
Fill(byte_t fill) Fill(byte_t fill)
{ {
@ -61,6 +73,12 @@ namespace llarp
return &m_Buffer; return &m_Buffer;
} }
llarp_buffer_t
Buffer() const
{
return m_Buffer;
}
size_t size_t
size() size()
{ {

@ -12,4 +12,6 @@
#include <llarp/messages/relay_ack.hpp> #include <llarp/messages/relay_ack.hpp>
#include <llarp/messages/relay_commit.hpp> #include <llarp/messages/relay_commit.hpp>
#include <llarp/messages/path_confirm.hpp>
#endif #endif

@ -0,0 +1,30 @@
#ifndef LLARP_MESSAGE_PATH_CONFIRM_HPP
#define LLARP_MESSAGE_PATH_CONFIRM_HPP
#include <llarp/routing_message.hpp>
namespace llarp
{
namespace routing
{
struct PathConfirmMessage : public IMessage
{
uint64_t pathLifetime;
uint64_t pathCreated;
PathConfirmMessage(uint64_t lifetime);
~PathConfirmMessage(){};
bool
BEncode(llarp_buffer_t* buf) const;
bool
BDecode(llarp_buffer_t* buf);
bool
HandleMessage(llarp_router* r) const;
};
} // namespace routing
} // namespace llarp
#endif

@ -2,10 +2,20 @@
#define LLARP_MESSAGES_RELAY_HPP #define LLARP_MESSAGES_RELAY_HPP
#include <llarp/link_message.hpp> #include <llarp/link_message.hpp>
#include <llarp/crypto.hpp>
#include <llarp/encrypted.hpp>
#include <llarp/path_types.hpp>
#include <vector>
namespace llarp namespace llarp
{ {
struct RelayUpstreamMessage : public ILinkMessage struct RelayUpstreamMessage : public ILinkMessage
{ {
PathID_t pathid;
Encrypted X;
TunnelNonce Y;
RelayUpstreamMessage();
RelayUpstreamMessage(const RouterID& from); RelayUpstreamMessage(const RouterID& from);
~RelayUpstreamMessage(); ~RelayUpstreamMessage();
@ -21,6 +31,10 @@ namespace llarp
struct RelayDownstreamMessage : public ILinkMessage struct RelayDownstreamMessage : public ILinkMessage
{ {
PathID_t pathid;
Encrypted X;
TunnelNonce Y;
RelayDownstreamMessage();
RelayDownstreamMessage(const RouterID& from); RelayDownstreamMessage(const RouterID& from);
~RelayDownstreamMessage(); ~RelayDownstreamMessage();
@ -33,6 +47,6 @@ namespace llarp
bool bool
HandleMessage(llarp_router* router) const; HandleMessage(llarp_router* router) const;
}; };
} } // namespace llarp
#endif #endif

@ -18,7 +18,8 @@ namespace llarp
PubKey commkey; PubKey commkey;
RouterID nextHop; RouterID nextHop;
TunnelNonce tunnelNonce; TunnelNonce tunnelNonce;
PathID_t pathid; PathID_t txid, rxid;
PoW *work = nullptr; PoW *work = nullptr;
uint64_t version = 0; uint64_t version = 0;

@ -6,10 +6,11 @@
#include <llarp/aligned.hpp> #include <llarp/aligned.hpp>
#include <llarp/crypto.hpp> #include <llarp/crypto.hpp>
#include <llarp/endpoint.hpp> #include <llarp/endpoint.hpp>
#include <llarp/messages/relay_ack.hpp> #include <llarp/messages/relay.hpp>
#include <llarp/messages/relay_commit.hpp> #include <llarp/messages/relay_commit.hpp>
#include <llarp/path_types.hpp> #include <llarp/path_types.hpp>
#include <llarp/router_id.hpp> #include <llarp/router_id.hpp>
#include <llarp/routing_message.hpp>
#include <list> #include <list>
#include <map> #include <map>
@ -17,21 +18,24 @@
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#define DEFAULT_PATH_LIFETIME (10 * 60 * 1000)
namespace llarp namespace llarp
{ {
struct TransitHopInfo struct TransitHopInfo
{ {
TransitHopInfo() = default; TransitHopInfo() = default;
TransitHopInfo(const TransitHopInfo& other);
TransitHopInfo(const RouterID& down, const LR_CommitRecord& record); TransitHopInfo(const RouterID& down, const LR_CommitRecord& record);
PathID_t pathID; PathID_t txID, rxID;
RouterID upstream; RouterID upstream;
RouterID downstream; RouterID downstream;
friend std::ostream& friend std::ostream&
operator<<(std::ostream& out, const TransitHopInfo& info) operator<<(std::ostream& out, const TransitHopInfo& info)
{ {
out << "<Transit Hop id=" << info.pathID; out << "<tx=" << info.txID << " rx=" << info.rxID;
out << " upstream=" << info.upstream << " downstream=" << info.downstream; out << " upstream=" << info.upstream << " downstream=" << info.downstream;
return out << ">"; return out << ">";
} }
@ -39,8 +43,8 @@ namespace llarp
bool bool
operator==(const TransitHopInfo& other) const operator==(const TransitHopInfo& other) const
{ {
return pathID == other.pathID && upstream == other.upstream return txID == other.txID && rxID == other.rxID
&& downstream == other.downstream; && upstream == other.upstream && downstream == other.downstream;
} }
bool bool
@ -52,7 +56,7 @@ namespace llarp
bool bool
operator<(const TransitHopInfo& other) const operator<(const TransitHopInfo& other) const
{ {
return pathID < other.pathID || upstream < other.upstream return txID < other.txID || rxID < other.rxID || upstream < other.upstream
|| downstream < other.downstream; || downstream < other.downstream;
} }
@ -61,10 +65,11 @@ namespace llarp
std::size_t std::size_t
operator()(TransitHopInfo const& a) const operator()(TransitHopInfo const& a) const
{ {
std::size_t idx0, idx1, idx2; std::size_t idx0, idx1, idx2, idx3;
memcpy(&idx0, a.upstream, sizeof(std::size_t)); memcpy(&idx0, a.upstream, sizeof(std::size_t));
memcpy(&idx1, a.downstream, sizeof(std::size_t)); memcpy(&idx1, a.downstream, sizeof(std::size_t));
memcpy(&idx2, a.pathID, sizeof(std::size_t)); memcpy(&idx2, a.txID, sizeof(std::size_t));
memcpy(&idx3, a.rxID, sizeof(std::size_t));
return idx0 ^ idx1 ^ idx2; return idx0 ^ idx1 ^ idx2;
} }
}; };
@ -81,34 +86,67 @@ namespace llarp
} }
}; };
struct TransitHop struct IHopHandler
{
virtual ~IHopHandler(){};
virtual bool
Expired(llarp_time_t now) const = 0;
virtual bool
SendRoutingMessage(const llarp::routing::IMessage* msg,
llarp_router* r) = 0;
// handle data in upstream direction
virtual bool
HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r) = 0;
// handle data in downstream direction
virtual bool
HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y,
llarp_router* r) = 0;
};
struct TransitHop : public IHopHandler
{ {
TransitHop() = default; TransitHop() = default;
TransitHop(const TransitHop& other);
TransitHopInfo info; TransitHopInfo info;
SharedSecret pathKey; SharedSecret pathKey;
llarp_time_t started; llarp_time_t started = 0;
// 10 minutes default // 10 minutes default
llarp_time_t lifetime = 360000; llarp_time_t lifetime = DEFAULT_PATH_LIFETIME;
llarp_proto_version_t version; llarp_proto_version_t version;
friend std::ostream&
operator<<(std::ostream& out, const TransitHop& h)
{
return out << "[TransitHop " << h.info << " started=" << h.started
<< " lifetime=" << h.lifetime << "]";
}
bool bool
Expired(llarp_time_t now) const; Expired(llarp_time_t now) const;
// forward data in upstream direction bool
void SendRoutingMessage(const llarp::routing::IMessage* msg, llarp_router* r);
ForwardUpstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r);
// forward data in downstream direction // handle data in upstream direction
void bool
ForwardDownstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r); HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r);
// handle data in downstream direction
bool
HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r);
}; };
/// configuration for a single hop when building a path /// configuration for a single hop when building a path
struct PathHopConfig struct PathHopConfig
{ {
/// path id /// path id
PathID_t pathID; PathID_t txID, rxID;
// router contact of router // router contact of router
llarp_rc router; llarp_rc router;
// temp public encryption key // temp public encryption key
@ -119,6 +157,8 @@ namespace llarp
RouterID upstream; RouterID upstream;
/// nonce for key exchange /// nonce for key exchange
TunnelNonce nonce; TunnelNonce nonce;
// lifetime
llarp_time_t lifetime = DEFAULT_PATH_LIFETIME;
~PathHopConfig(); ~PathHopConfig();
PathHopConfig(); PathHopConfig();
@ -133,7 +173,7 @@ namespace llarp
}; };
/// A path we made /// A path we made
struct Path struct Path : public IHopHandler
{ {
typedef std::vector< PathHopConfig > HopList; typedef std::vector< PathHopConfig > HopList;
HopList hops; HopList hops;
@ -142,17 +182,28 @@ namespace llarp
Path(llarp_path_hops* path); Path(llarp_path_hops* path);
void bool
EncryptAndSend(llarp_buffer_t buf, llarp_router* r); Expired(llarp_time_t now) const;
void bool
DecryptAndRecv(llarp_buffer_t buf, IEndpointHandler* handler); SendRoutingMessage(const llarp::routing::IMessage* msg, llarp_router* r);
bool
HandleRoutingMessage(llarp_buffer_t buf, llarp_router* r);
// handle data in upstream direction
bool
HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r);
// handle data in downstream direction
bool
HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r);
const PathID_t& const PathID_t&
PathID() const; PathID() const;
RouterID RouterID
Upstream(); Upstream() const;
}; };
enum PathBuildStatus enum PathBuildStatus
@ -185,11 +236,14 @@ namespace llarp
bool bool
HandleRelayCommit(const LR_CommitMessage* msg); HandleRelayCommit(const LR_CommitMessage* msg);
bool
HandleRelayAck(const LR_AckMessage* msg);
void void
PutTransitHop(const TransitHop& hop); PutTransitHop(TransitHop* hop);
IHopHandler*
GetByUpstream(const RouterID& id, const PathID_t& path);
IHopHandler*
GetDownstream(const RouterID& id, const PathID_t& path);
bool bool
ForwardLRCM(const RouterID& nextHop, std::deque< EncryptedFrame >& frames); ForwardLRCM(const RouterID& nextHop, std::deque< EncryptedFrame >& frames);
@ -197,11 +251,16 @@ namespace llarp
bool bool
HopIsUs(const PubKey& k) const; HopIsUs(const PubKey& k) const;
bool
HandleLRUM(const RelayUpstreamMessage* msg);
bool
HandleLRDM(const RelayDownstreamMessage* msg);
void void
AddOwnPath(Path* p); AddOwnPath(Path* p);
typedef std::unordered_multimap< PathID_t, TransitHop, PathIDHash > typedef std::multimap< PathID_t, TransitHop* > TransitHopsMap_t;
TransitHopsMap_t;
typedef std::pair< std::mutex, TransitHopsMap_t > SyncTransitMap_t; typedef std::pair< std::mutex, TransitHopsMap_t > SyncTransitMap_t;
@ -218,6 +277,9 @@ namespace llarp
llarp_logic* llarp_logic*
Logic(); Logic();
llarp_router*
Router();
byte_t* byte_t*
EncryptionSecretKey(); EncryptionSecretKey();
@ -227,6 +289,7 @@ namespace llarp
private: private:
llarp_router* m_Router; llarp_router* m_Router;
SyncTransitMap_t m_TransitPaths; SyncTransitMap_t m_TransitPaths;
SyncTransitMap_t m_Paths;
SyncOwnedPathsMap_t m_OurPaths; SyncOwnedPathsMap_t m_OurPaths;
bool m_AllowTransit; bool m_AllowTransit;

@ -0,0 +1,30 @@
#ifndef LLARP_ROUTING_MESSAGE_HPP
#define LLARP_ROUTING_MESSAGE_HPP
#include <llarp/buffer.h>
#include <llarp/router.h>
#include <llarp/path_types.hpp>
namespace llarp
{
namespace routing
{
struct IMessage
{
llarp::PathID_t from;
virtual ~IMessage(){};
virtual bool
BEncode(llarp_buffer_t* buf) const = 0;
virtual bool
BDecode(llarp_buffer_t* buf) = 0;
virtual bool
HandleMessage(llarp_router* r) const = 0;
};
} // namespace routing
} // namespace llarp
#endif

@ -5,6 +5,11 @@
namespace llarp namespace llarp
{ {
Encrypted::Encrypted()
{
UpdateBuffer();
}
Encrypted::Encrypted(const byte_t* buf, size_t sz) : _sz(sz) Encrypted::Encrypted(const byte_t* buf, size_t sz) : _sz(sz)
{ {
_data = new byte_t[sz]; _data = new byte_t[sz];

@ -1396,8 +1396,8 @@ namespace iwp
llarp::Debug("removing session ", addr); llarp::Debug("removing session ", addr);
UnmapAddr(addr); UnmapAddr(addr);
session *s = static_cast< session * >(itr->second.impl); session *s = static_cast< session * >(itr->second.impl);
m_sessions.erase(itr);
s->done(); s->done();
m_sessions.erase(itr);
if(s->frames) if(s->frames)
{ {
llarp::Warn("session has ", s->frames, llarp::Warn("session has ", s->frames,
@ -1903,18 +1903,19 @@ namespace iwp
self->establish_job_id = 0; self->establish_job_id = 0;
if(self->establish_job) if(self->establish_job)
{ {
self->establish_job->link = self->serv->parent; auto job = self->establish_job;
self->establish_job = nullptr;
job->link = self->serv->parent;
if(self->IsEstablished()) if(self->IsEstablished())
{ {
self->establish_job->session = self->parent; job->session = self->parent;
} }
else else
{ {
// timer timeout // timer timeout
self->establish_job->session = nullptr; job->session = nullptr;
} }
self->establish_job->result(self->establish_job); job->result(job);
self->establish_job = nullptr;
} }
} }
@ -1950,22 +1951,23 @@ namespace iwp
} }
} // namespace iwp } // namespace iwp
extern "C" { extern "C"
void
iwp_link_init(struct llarp_link *link, struct llarp_iwp_args args)
{ {
link->impl = iwp::link_alloc(args.router, args.keyfile, args.crypto, void
args.logic, args.cryptoworker); iwp_link_init(struct llarp_link *link, struct llarp_iwp_args args)
link->name = iwp::link_name; {
link->get_our_address = iwp::link_get_addr; link->impl = iwp::link_alloc(args.router, args.keyfile, args.crypto,
link->configure = iwp::link_configure; args.logic, args.cryptoworker);
link->start_link = iwp::link_start; link->name = iwp::link_name;
link->stop_link = iwp::link_stop; link->get_our_address = iwp::link_get_addr;
link->iter_sessions = iwp::link_iter_sessions; link->configure = iwp::link_configure;
link->try_establish = iwp::link_try_establish; link->start_link = iwp::link_start;
link->has_session_to = iwp::server::HasSessionToRouter; link->stop_link = iwp::link_stop;
link->sendto = iwp::server::SendToSession; link->iter_sessions = iwp::link_iter_sessions;
link->mark_session_active = iwp::link_mark_session_active; link->try_establish = iwp::link_try_establish;
link->free_impl = iwp::link_free; link->has_session_to = iwp::server::HasSessionToRouter;
} link->sendto = iwp::server::SendToSession;
link->mark_session_active = iwp::link_mark_session_active;
link->free_impl = iwp::link_free;
}
} }

@ -1,6 +1,7 @@
#include <deque> #include <deque>
#include <llarp/encrypted_frame.hpp> #include <llarp/encrypted_frame.hpp>
#include <llarp/path.hpp> #include <llarp/path.hpp>
#include "buffer.hpp"
#include "router.hpp" #include "router.hpp"
namespace llarp namespace llarp
@ -69,6 +70,20 @@ namespace llarp
} }
return m_Router->SendToOrQueue(nextHop, msg); return m_Router->SendToOrQueue(nextHop, msg);
} }
template < typename Map_t, typename Key_t, typename CheckValue_t >
IHopHandler*
MapGet(Map_t& map, const Key_t& k, CheckValue_t check)
{
std::unique_lock< std::mutex > lock(map.first);
auto itr = map.second.find(k);
while(itr != map.second.end())
{
if(check(itr->second))
return itr->second;
++itr;
}
return nullptr;
}
template < typename Map_t, typename Key_t, typename CheckValue_t > template < typename Map_t, typename Key_t, typename CheckValue_t >
bool bool
@ -93,6 +108,21 @@ namespace llarp
map.second.emplace(k, v); map.second.emplace(k, v);
} }
template < typename Map_t, typename Key_t, typename Check_t >
void
MapDel(Map_t& map, const Key_t& k, Check_t check)
{
std::unique_lock< std::mutex > lock(map.first);
auto itr = map.second.find(k);
while(itr != map.second.end())
{
if(check(itr->second))
itr = map.second.erase(itr);
else
++itr;
}
}
void void
PathContext::AddOwnPath(Path* path) PathContext::AddOwnPath(Path* path)
{ {
@ -102,9 +132,22 @@ namespace llarp
bool bool
PathContext::HasTransitHop(const TransitHopInfo& info) PathContext::HasTransitHop(const TransitHopInfo& info)
{ {
return MapHas( return MapHas(m_TransitPaths, info.pathID, [info](TransitHop* hop) -> bool {
m_TransitPaths, info.pathID, return info == hop->info;
[info](const TransitHop& hop) -> bool { return info == hop.info; }); });
}
IHopHandler*
PathContext::GetByUpstream(const RouterID& remote, const PathID_t& id)
{
auto own = MapGet(m_OurPaths, id, [remote](const Path* p) -> bool {
return p->Upstream() == remote;
});
if(own)
return own;
return MapGet(m_TransitPaths, id, [remote](const TransitHop* hop) -> bool {
return hop->info.upstream == remote;
});
} }
const byte_t* const byte_t*
@ -113,10 +156,17 @@ namespace llarp
return m_Router->pubkey(); return m_Router->pubkey();
} }
llarp_router*
PathContext::Router()
{
return m_Router;
}
void void
PathContext::PutTransitHop(const TransitHop& hop) PathContext::PutTransitHop(TransitHop* hop)
{ {
MapPut(m_TransitPaths, hop.info.pathID, hop); MapPut(m_TransitPaths, hop->info.txID, hop);
MapPut(m_TransitPaths, hop->info.rxID, hop);
} }
void void
@ -126,45 +176,110 @@ namespace llarp
auto now = llarp_time_now_ms(); auto now = llarp_time_now_ms();
auto& map = m_TransitPaths.second; auto& map = m_TransitPaths.second;
auto itr = map.begin(); auto itr = map.begin();
std::set< TransitHop* > removePaths;
while(itr != map.end()) while(itr != map.end())
{ {
if(itr->second.Expired(now)) if(itr->second->Expired(now))
itr = map.erase(itr); {
else TransitHop* path = itr->second;
++itr; llarp::Info("transit path expired ", path);
removePaths.insert(path);
}
++itr;
}
for(auto& p : removePaths)
{
map.erase(p->info.txID);
map.erase(p->info.rxID);
delete p;
} }
} }
Path::Path(llarp_path_hops* h) : hops(h->numHops)
{
for(size_t idx = 0; idx < h->numHops; ++idx)
{
llarp_rc_copy(&hops[idx].router, &h->hops[idx].router);
}
}
const PathID_t&
Path::TXID() const
{
return hops[0].pathTX;
}
const PathID_t&
Path::RXID() const
{
return hops[0].pathRX;
}
RouterID
Path::Upstream() const
{
return hops[0].router.pubkey;
}
bool bool
TransitHop::Expired(llarp_time_t now) const Path::HandleUpstream(llarp_buffer_t buf, const TunnelNonce& Y,
llarp_router* r)
{ {
return now - started > lifetime; for(const auto& hop : hops)
{
r->crypto.xchacha20(buf, hop.shared, Y);
}
RelayUpstreamMessage* msg = new RelayUpstreamMessage;
msg->X = buf;
msg->Y = Y;
msg->pathid = PathID();
msg->pathid.data_l()[1] = 0;
return r->SendToOrQueue(Upstream(), msg);
} }
TransitHopInfo::TransitHopInfo(const RouterID& down, bool
const LR_CommitRecord& record) Path::Expired(llarp_time_t now) const
: pathID(record.pathid), upstream(record.nextHop), downstream(down)
{ {
return now - buildStarted > hops[0].lifetime;
} }
Path::Path(llarp_path_hops* h) : hops(h->numHops) bool
Path::HandleDownstream(llarp_buffer_t buf, const TunnelNonce& Y,
llarp_router* r)
{ {
for(size_t idx = 0; idx < h->numHops; ++idx) size_t idx = hops.size() - 1;
while(idx >= 0)
{ {
llarp_rc_copy(&hops[idx].router, &h->hops[idx].router); r->crypto.xchacha20(buf, hops[idx].shared, Y);
if(idx)
idx--;
else
break;
} }
return HandleRoutingMessage(buf, r);
} }
const PathID_t& bool
Path::PathID() const Path::HandleRoutingMessage(llarp_buffer_t buf, llarp_router* r)
{ {
return hops[0].pathID; // TODO: implement me
return true;
} }
RouterID bool
Path::Upstream() Path::SendRoutingMessage(const llarp::routing::IMessage* msg, llarp_router* r)
{ {
return hops[0].router.pubkey; byte_t tmp[MAX_LINK_MSG_SIZE / 2];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
if(!msg->BEncode(&buf))
return false;
// rewind
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
// make nonce
TunnelNonce N;
N.Randomize();
return HandleUpstream(buf, N, r);
} }
} // namespace llarp } // namespace llarp

@ -0,0 +1,41 @@
#include <llarp/time.h>
#include <llarp/bencode.hpp>
#include <llarp/messages/path_confirm.hpp>
namespace llarp
{
namespace routing
{
PathConfirmMessage::PathConfirmMessage(uint64_t lifetime)
: pathLifetime(lifetime), pathCreated(llarp_time_now_ms())
{
}
bool
PathConfirmMessage::BEncode(llarp_buffer_t* buf) const
{
if(!bencode_start_dict(buf))
return false;
if(!BEncodeWriteDictMsgType(buf, "A", "P"))
return false;
if(!BEncodeWriteDictInt(buf, "L", pathLifetime))
return false;
if(!BEncodeWriteDictInt(buf, "S", pathCreated))
return false;
return bencode_end(buf);
}
bool
PathConfirmMessage::BDecode(llarp_buffer_t* buf)
{
return false;
}
bool
PathConfirmMessage::HandleMessage(llarp_router* r) const
{
return true;
}
} // namespace routing
} // namespace llarp

@ -47,8 +47,6 @@ namespace llarp
abort(); abort();
return; return;
} }
// randomize hop's path id
hop.pathID.Randomize();
++ctx->idx; ++ctx->idx;

@ -1,5 +1,7 @@
#include <llarp/bencode.hpp> #include <llarp/bencode.hpp>
#include <llarp/messages/path_confirm.hpp>
#include <llarp/messages/relay_commit.hpp> #include <llarp/messages/relay_commit.hpp>
#include "buffer.hpp"
#include "logger.hpp" #include "logger.hpp"
#include "router.hpp" #include "router.hpp"
@ -73,7 +75,9 @@ namespace llarp
return false; return false;
if(!BEncodeWriteDictEntry("n", tunnelNonce, buf)) if(!BEncodeWriteDictEntry("n", tunnelNonce, buf))
return false; return false;
if(!BEncodeWriteDictEntry("p", pathid, buf)) if(!BEncodeWriteDictEntry("r", rxid, buf))
return false;
if(!BEncodeWriteDictEntry("t", txid, buf))
return false; return false;
if(!bencode_write_version_entry(buf)) if(!bencode_write_version_entry(buf))
return false; return false;
@ -106,7 +110,9 @@ namespace llarp
if(!BEncodeMaybeReadDictEntry("n", self->tunnelNonce, read, *key, if(!BEncodeMaybeReadDictEntry("n", self->tunnelNonce, read, *key,
r->buffer)) r->buffer))
return false; return false;
if(!BEncodeMaybeReadDictEntry("p", self->pathid, read, *key, r->buffer)) if(!BEncodeMaybeReadDictEntry("r", self->rxid, read, *key, r->buffer))
return false;
if(!BEncodeMaybeReadDictEntry("t", self->txid, read, *key, r->buffer))
return false; return false;
if(!BEncodeMaybeReadVersion("v", self->version, LLARP_PROTO_VERSION, read, if(!BEncodeMaybeReadVersion("v", self->version, LLARP_PROTO_VERSION, read,
*key, r->buffer)) *key, r->buffer))
@ -144,7 +150,7 @@ namespace llarp
return false; return false;
} }
return nextHop == other.nextHop && commkey == other.commkey return nextHop == other.nextHop && commkey == other.commkey
&& pathid == other.pathid; && txid == other.txid && rxid == other.rxid;
} }
struct LRCMFrameDecrypt struct LRCMFrameDecrypt
@ -156,15 +162,15 @@ namespace llarp
// decrypted record // decrypted record
LR_CommitRecord record; LR_CommitRecord record;
// the actual hop // the actual hop
TransitHop hop; TransitHop* hop;
LRCMFrameDecrypt(PathContext* ctx, Decrypter* dec, LRCMFrameDecrypt(PathContext* ctx, Decrypter* dec,
const LR_CommitMessage* commit) const LR_CommitMessage* commit)
: decrypter(dec), context(ctx) : decrypter(dec), context(ctx), hop(new TransitHop)
{ {
for(const auto& f : commit->frames) for(const auto& f : commit->frames)
frames.push_back(f); frames.push_back(f);
hop.info.downstream = commit->remote; hop->info.downstream = commit->remote;
} }
~LRCMFrameDecrypt() ~LRCMFrameDecrypt()
@ -177,19 +183,26 @@ namespace llarp
SendLRCM(void* user) SendLRCM(void* user)
{ {
LRCMFrameDecrypt* self = static_cast< LRCMFrameDecrypt* >(user); LRCMFrameDecrypt* self = static_cast< LRCMFrameDecrypt* >(user);
self->context->ForwardLRCM(self->hop.info.upstream, self->frames); self->context->ForwardLRCM(self->hop->info.upstream, self->frames);
delete self; delete self;
} }
static void static void
SendLRAM(void* user) SendPathConfirm(void* user)
{ {
LRCMFrameDecrypt* self = static_cast< LRCMFrameDecrypt* >(user);
llarp::routing::PathConfirmMessage confirm(self->hop->lifetime);
if(!self->hop->SendRoutingMessage(&confirm, self->context->Router()))
{
llarp::Error("failed to send path confirmation for ", self->hop->info);
}
delete self;
} }
static void static void
HandleDecrypted(llarp_buffer_t* buf, LRCMFrameDecrypt* self) HandleDecrypted(llarp_buffer_t* buf, LRCMFrameDecrypt* self)
{ {
auto& info = self->hop.info; auto& info = self->hop->info;
if(!buf) if(!buf)
{ {
llarp::Error("LRCM decrypt failed from ", info.downstream); llarp::Error("LRCM decrypt failed from ", info.downstream);
@ -206,7 +219,8 @@ namespace llarp
return; return;
} }
info.pathID = self->record.pathid; info.txID = self->record.txid;
info.rxID = self->record.rxid;
info.upstream = self->record.nextHop; info.upstream = self->record.nextHop;
if(self->context->HasTransitHop(info)) if(self->context->HasTransitHop(info))
{ {
@ -216,7 +230,7 @@ namespace llarp
} }
// generate path key as we are in a worker thread // generate path key as we are in a worker thread
auto DH = self->context->Crypto()->dh_server; auto DH = self->context->Crypto()->dh_server;
if(!DH(self->hop.pathKey, self->record.commkey, if(!DH(self->hop->pathKey, self->record.commkey,
self->context->EncryptionSecretKey(), self->record.tunnelNonce)) self->context->EncryptionSecretKey(), self->record.tunnelNonce))
{ {
llarp::Error("LRCM DH Failed ", info); llarp::Error("LRCM DH Failed ", info);
@ -229,12 +243,12 @@ namespace llarp
{ {
llarp::Info("LRCM extended lifetime by ", llarp::Info("LRCM extended lifetime by ",
self->record.work->extendedLifetime, " seconds for ", info); self->record.work->extendedLifetime, " seconds for ", info);
self->hop.lifetime += 1000 * self->record.work->extendedLifetime; self->hop->lifetime += 1000 * self->record.work->extendedLifetime;
} }
// TODO: check if we really want to accept it // TODO: check if we really want to accept it
self->hop.started = llarp_time_now_ms(); self->hop->started = llarp_time_now_ms();
llarp::Info("Accepted ", self->hop.info); llarp::Info("Accepted ", self->hop->info);
self->context->PutTransitHop(self->hop); self->context->PutTransitHop(self->hop);
size_t sz = self->frames.front().size(); size_t sz = self->frames.front().size();
@ -250,7 +264,7 @@ namespace llarp
// we are the farthest hop // we are the farthest hop
llarp::Info("We are the farthest hop for ", info); llarp::Info("We are the farthest hop for ", info);
// send a LRAM down the path // send a LRAM down the path
llarp_logic_queue_job(self->context->Logic(), {self, &SendLRAM}); llarp_logic_queue_job(self->context->Logic(), {self, &SendPathConfirm});
} }
else else
{ {

@ -1,5 +1,8 @@
#include <llarp/bencode.hpp>
#include <llarp/messages/relay.hpp> #include <llarp/messages/relay.hpp>
#include "router.hpp"
namespace llarp namespace llarp
{ {
RelayUpstreamMessage::RelayUpstreamMessage(const RouterID &from) RelayUpstreamMessage::RelayUpstreamMessage(const RouterID &from)
@ -7,6 +10,10 @@ namespace llarp
{ {
} }
RelayUpstreamMessage::RelayUpstreamMessage() : ILinkMessage()
{
}
RelayUpstreamMessage::~RelayUpstreamMessage() RelayUpstreamMessage::~RelayUpstreamMessage()
{ {
} }
@ -35,25 +42,62 @@ namespace llarp
{ {
} }
RelayDownstreamMessage::RelayDownstreamMessage() : ILinkMessage()
{
}
RelayDownstreamMessage::~RelayDownstreamMessage() RelayDownstreamMessage::~RelayDownstreamMessage()
{ {
} }
bool bool
RelayDownstreamMessage::BEncode(llarp_buffer_t *buf) const RelayDownstreamMessage::BEncode(llarp_buffer_t *buf) const
{ {
// TODO: implement me if(!bencode_start_dict(buf))
return false; return false;
if(!BEncodeWriteDictMsgType(buf, "a", "d"))
return false;
if(!BEncodeWriteDictEntry("p", pathid, buf))
return false;
if(!BEncodeWriteDictInt(buf, "v", LLARP_PROTO_VERSION))
return false;
if(!BEncodeWriteDictEntry("x", X, buf))
return false;
if(!BEncodeWriteDictEntry("y", Y, buf))
return false;
return bencode_end(buf);
} }
bool bool
RelayDownstreamMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t *buf) RelayDownstreamMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t *buf)
{ {
return false; bool read = false;
if(!BEncodeMaybeReadDictEntry("p", pathid, read, key, buf))
return false;
if(!BEncodeMaybeReadVersion("v", version, LLARP_PROTO_VERSION, read, key,
buf))
return false;
if(!BEncodeMaybeReadDictEntry("x", X, read, key, buf))
return false;
if(!BEncodeMaybeReadDictEntry("y", Y, read, key, buf))
return false;
return read;
} }
bool bool
RelayDownstreamMessage::HandleMessage(llarp_router *router) const RelayDownstreamMessage::HandleMessage(llarp_router *router) const
{ {
PathID_t id = pathid;
id.data_l()[0] = 0;
auto path = router->paths.GetByUpstream(remote, id);
if(path)
{
return path->HandleDownstream(X.Buffer(), Y, router);
}
else
{
llarp::Warn("No such path upstream=", remote, " pathid=", id);
}
return false; return false;
} }
} } // namespace llarp

@ -54,7 +54,7 @@ llarp_router::HandleRecvLinkMessage(llarp_link_session *session,
bool bool
llarp_router::SendToOrQueue(const llarp::RouterID &remote, llarp_router::SendToOrQueue(const llarp::RouterID &remote,
llarp::ILinkMessage *msg) const llarp::ILinkMessage *msg)
{ {
llarp_link *chosen = nullptr; llarp_link *chosen = nullptr;
if(!outboundLink->has_session_to(outboundLink, remote)) if(!outboundLink->has_session_to(outboundLink, remote))
@ -444,7 +444,7 @@ llarp_router::send_padded_message(llarp_link_session_iter *itr,
} }
void void
llarp_router::SendTo(llarp::RouterID remote, llarp::ILinkMessage *msg, llarp_router::SendTo(llarp::RouterID remote, const llarp::ILinkMessage *msg,
llarp_link *link) llarp_link *link)
{ {
llarp_buffer_t buf = llarp_buffer_t buf =

@ -77,7 +77,7 @@ struct llarp_router
llarp_link *outboundLink = nullptr; llarp_link *outboundLink = nullptr;
std::list< llarp_link * > inboundLinks; std::list< llarp_link * > inboundLinks;
typedef std::queue< llarp::ILinkMessage * > MessageQueue; typedef std::queue< const llarp::ILinkMessage * > MessageQueue;
/// outbound message queue /// outbound message queue
std::map< llarp::RouterID, MessageQueue > outboundMesssageQueue; std::map< llarp::RouterID, MessageQueue > outboundMesssageQueue;
@ -142,11 +142,11 @@ struct llarp_router
/// NOT threadsafe /// NOT threadsafe
/// MUST be called in the logic thread /// MUST be called in the logic thread
bool bool
SendToOrQueue(const llarp::RouterID &remote, llarp::ILinkMessage *msg); SendToOrQueue(const llarp::RouterID &remote, const llarp::ILinkMessage *msg);
/// sendto or drop /// sendto or drop
void void
SendTo(llarp::RouterID remote, llarp::ILinkMessage *msg, SendTo(llarp::RouterID remote, const llarp::ILinkMessage *msg,
llarp_link *chosen = nullptr); llarp_link *chosen = nullptr);
/// manually flush outbound message queue for just 1 router /// manually flush outbound message queue for just 1 router

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

@ -43,7 +43,8 @@ TEST_F(FrameTest, TestFrameCrypto)
LRCR record; LRCR record;
record.nextHop.Fill(1); record.nextHop.Fill(1);
record.tunnelNonce.Fill(2); record.tunnelNonce.Fill(2);
record.pathid.Fill(3); record.rxid.Fill(3);
record.txid.Fill(4);
auto buf = f.Buffer(); auto buf = f.Buffer();
buf->cur = buf->base + EncryptedFrame::OverheadSize; buf->cur = buf->base + EncryptedFrame::OverheadSize;

Loading…
Cancel
Save