From 39c63432befb8b66d008e01e53ab45eccbd0e5fa Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 21 Jun 2018 20:25:30 -0400 Subject: [PATCH] ALMOST got path building working --- CMakeLists.txt | 2 + doc/proto_v0.txt | 3 +- include/llarp/aligned.hpp | 6 + include/llarp/encrypted.hpp | 20 ++- include/llarp/messages.hpp | 2 + include/llarp/messages/path_confirm.hpp | 30 +++++ include/llarp/messages/relay.hpp | 16 ++- include/llarp/messages/relay_commit.hpp | 3 +- include/llarp/path.hpp | 123 +++++++++++++----- include/llarp/routing_message.hpp | 30 +++++ llarp/encrypted_frame.cpp | 5 + llarp/iwp_link.cpp | 48 +++---- llarp/path.cpp | 161 ++++++++++++++++++++---- llarp/path_confirm.cpp | 41 ++++++ llarp/pathbuilder.cpp | 2 - llarp/relay_commit.cpp | 44 ++++--- llarp/relay_up_down.cpp | 52 +++++++- llarp/router.cpp | 4 +- llarp/router.hpp | 6 +- llarp/transit_hop.cpp | 84 +++++++++++++ test/encrypted_frame_unittest.cpp | 3 +- 21 files changed, 578 insertions(+), 107 deletions(-) create mode 100644 include/llarp/messages/path_confirm.hpp create mode 100644 include/llarp/routing_message.hpp create mode 100644 llarp/path_confirm.cpp create mode 100644 llarp/transit_hop.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 793bbcca0..84bfd3a0e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,6 +124,7 @@ set(LIB_SRC llarp/nodedb.cpp llarp/path.cpp llarp/pathbuilder.cpp + llarp/path_confirm.cpp llarp/proofofwork.cpp llarp/relay_ack.cpp llarp/relay_commit.cpp @@ -131,6 +132,7 @@ set(LIB_SRC llarp/router_contact.cpp llarp/router.cpp llarp/threadpool.cpp + llarp/transit_hop.cpp llarp/testnet.c llarp/time.cpp llarp/timer.cpp diff --git a/doc/proto_v0.txt b/doc/proto_v0.txt index d30a31eaf..dccb5b0a3 100644 --- a/doc/proto_v0.txt +++ b/doc/proto_v0.txt @@ -294,7 +294,8 @@ the path is extended by w.y seconds c: "<32 byte public encryption key used for upstream>", i: "<32 byte RC.k of next hop>", 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, w: proof of work } diff --git a/include/llarp/aligned.hpp b/include/llarp/aligned.hpp index f705c1323..9cb7d84a9 100644 --- a/include/llarp/aligned.hpp +++ b/include/llarp/aligned.hpp @@ -19,6 +19,12 @@ namespace llarp 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) { for(size_t idx = 0; idx < sz; ++idx) diff --git a/include/llarp/encrypted.hpp b/include/llarp/encrypted.hpp index 05e46e514..36cdd6036 100644 --- a/include/llarp/encrypted.hpp +++ b/include/llarp/encrypted.hpp @@ -12,7 +12,7 @@ namespace llarp struct Encrypted { Encrypted(Encrypted&&) = delete; - + Encrypted(); Encrypted(const byte_t* buf, size_t sz); Encrypted(size_t sz); ~Encrypted(); @@ -23,6 +23,18 @@ namespace llarp 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 Fill(byte_t fill) { @@ -61,6 +73,12 @@ namespace llarp return &m_Buffer; } + llarp_buffer_t + Buffer() const + { + return m_Buffer; + } + size_t size() { diff --git a/include/llarp/messages.hpp b/include/llarp/messages.hpp index 2539d0528..93cce0649 100644 --- a/include/llarp/messages.hpp +++ b/include/llarp/messages.hpp @@ -12,4 +12,6 @@ #include #include +#include + #endif diff --git a/include/llarp/messages/path_confirm.hpp b/include/llarp/messages/path_confirm.hpp new file mode 100644 index 000000000..6ada84510 --- /dev/null +++ b/include/llarp/messages/path_confirm.hpp @@ -0,0 +1,30 @@ +#ifndef LLARP_MESSAGE_PATH_CONFIRM_HPP +#define LLARP_MESSAGE_PATH_CONFIRM_HPP + +#include + +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 \ No newline at end of file diff --git a/include/llarp/messages/relay.hpp b/include/llarp/messages/relay.hpp index 59379b9b4..5e1db0929 100644 --- a/include/llarp/messages/relay.hpp +++ b/include/llarp/messages/relay.hpp @@ -2,10 +2,20 @@ #define LLARP_MESSAGES_RELAY_HPP #include +#include +#include +#include +#include + namespace llarp { struct RelayUpstreamMessage : public ILinkMessage { + PathID_t pathid; + Encrypted X; + TunnelNonce Y; + + RelayUpstreamMessage(); RelayUpstreamMessage(const RouterID& from); ~RelayUpstreamMessage(); @@ -21,6 +31,10 @@ namespace llarp struct RelayDownstreamMessage : public ILinkMessage { + PathID_t pathid; + Encrypted X; + TunnelNonce Y; + RelayDownstreamMessage(); RelayDownstreamMessage(const RouterID& from); ~RelayDownstreamMessage(); @@ -33,6 +47,6 @@ namespace llarp bool HandleMessage(llarp_router* router) const; }; -} +} // namespace llarp #endif diff --git a/include/llarp/messages/relay_commit.hpp b/include/llarp/messages/relay_commit.hpp index a7648b83f..8c58baac2 100644 --- a/include/llarp/messages/relay_commit.hpp +++ b/include/llarp/messages/relay_commit.hpp @@ -18,7 +18,8 @@ namespace llarp PubKey commkey; RouterID nextHop; TunnelNonce tunnelNonce; - PathID_t pathid; + PathID_t txid, rxid; + PoW *work = nullptr; uint64_t version = 0; diff --git a/include/llarp/path.hpp b/include/llarp/path.hpp index 753f4f40a..77f3c067f 100644 --- a/include/llarp/path.hpp +++ b/include/llarp/path.hpp @@ -6,10 +6,11 @@ #include #include #include -#include +#include #include #include #include +#include #include #include @@ -17,21 +18,24 @@ #include #include +#define DEFAULT_PATH_LIFETIME (10 * 60 * 1000) + namespace llarp { struct TransitHopInfo { TransitHopInfo() = default; + TransitHopInfo(const TransitHopInfo& other); TransitHopInfo(const RouterID& down, const LR_CommitRecord& record); - PathID_t pathID; + PathID_t txID, rxID; RouterID upstream; RouterID downstream; friend std::ostream& operator<<(std::ostream& out, const TransitHopInfo& info) { - out << ""; } @@ -39,8 +43,8 @@ namespace llarp bool operator==(const TransitHopInfo& other) const { - return pathID == other.pathID && upstream == other.upstream - && downstream == other.downstream; + return txID == other.txID && rxID == other.rxID + && upstream == other.upstream && downstream == other.downstream; } bool @@ -52,7 +56,7 @@ namespace llarp bool 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; } @@ -61,10 +65,11 @@ namespace llarp std::size_t 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(&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; } }; @@ -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(const TransitHop& other); + TransitHopInfo info; SharedSecret pathKey; - llarp_time_t started; + llarp_time_t started = 0; // 10 minutes default - llarp_time_t lifetime = 360000; + llarp_time_t lifetime = DEFAULT_PATH_LIFETIME; llarp_proto_version_t version; + friend std::ostream& + operator<<(std::ostream& out, const TransitHop& h) + { + return out << "[TransitHop " << h.info << " started=" << h.started + << " lifetime=" << h.lifetime << "]"; + } + bool Expired(llarp_time_t now) const; - // forward data in upstream direction - void - ForwardUpstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r); + bool + SendRoutingMessage(const llarp::routing::IMessage* msg, llarp_router* r); - // forward data in downstream direction - void - ForwardDownstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r); + // handle data in upstream direction + bool + HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r); + + // handle data in downstream direction + bool + HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r); }; /// configuration for a single hop when building a path struct PathHopConfig { /// path id - PathID_t pathID; + PathID_t txID, rxID; // router contact of router llarp_rc router; // temp public encryption key @@ -119,6 +157,8 @@ namespace llarp RouterID upstream; /// nonce for key exchange TunnelNonce nonce; + // lifetime + llarp_time_t lifetime = DEFAULT_PATH_LIFETIME; ~PathHopConfig(); PathHopConfig(); @@ -133,7 +173,7 @@ namespace llarp }; /// A path we made - struct Path + struct Path : public IHopHandler { typedef std::vector< PathHopConfig > HopList; HopList hops; @@ -142,17 +182,28 @@ namespace llarp Path(llarp_path_hops* path); - void - EncryptAndSend(llarp_buffer_t buf, llarp_router* r); + bool + Expired(llarp_time_t now) const; - void - DecryptAndRecv(llarp_buffer_t buf, IEndpointHandler* handler); + bool + 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& PathID() const; RouterID - Upstream(); + Upstream() const; }; enum PathBuildStatus @@ -185,11 +236,14 @@ namespace llarp bool HandleRelayCommit(const LR_CommitMessage* msg); - bool - HandleRelayAck(const LR_AckMessage* msg); - 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 ForwardLRCM(const RouterID& nextHop, std::deque< EncryptedFrame >& frames); @@ -197,11 +251,16 @@ namespace llarp bool HopIsUs(const PubKey& k) const; + bool + HandleLRUM(const RelayUpstreamMessage* msg); + + bool + HandleLRDM(const RelayDownstreamMessage* msg); + void AddOwnPath(Path* p); - typedef std::unordered_multimap< PathID_t, TransitHop, PathIDHash > - TransitHopsMap_t; + typedef std::multimap< PathID_t, TransitHop* > TransitHopsMap_t; typedef std::pair< std::mutex, TransitHopsMap_t > SyncTransitMap_t; @@ -218,6 +277,9 @@ namespace llarp llarp_logic* Logic(); + llarp_router* + Router(); + byte_t* EncryptionSecretKey(); @@ -227,6 +289,7 @@ namespace llarp private: llarp_router* m_Router; SyncTransitMap_t m_TransitPaths; + SyncTransitMap_t m_Paths; SyncOwnedPathsMap_t m_OurPaths; bool m_AllowTransit; diff --git a/include/llarp/routing_message.hpp b/include/llarp/routing_message.hpp new file mode 100644 index 000000000..dd29344bc --- /dev/null +++ b/include/llarp/routing_message.hpp @@ -0,0 +1,30 @@ +#ifndef LLARP_ROUTING_MESSAGE_HPP +#define LLARP_ROUTING_MESSAGE_HPP + +#include +#include +#include + +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 \ No newline at end of file diff --git a/llarp/encrypted_frame.cpp b/llarp/encrypted_frame.cpp index 070ce68be..90ea2fa23 100644 --- a/llarp/encrypted_frame.cpp +++ b/llarp/encrypted_frame.cpp @@ -5,6 +5,11 @@ namespace llarp { + Encrypted::Encrypted() + { + UpdateBuffer(); + } + Encrypted::Encrypted(const byte_t* buf, size_t sz) : _sz(sz) { _data = new byte_t[sz]; diff --git a/llarp/iwp_link.cpp b/llarp/iwp_link.cpp index 2434672a8..579594bd0 100644 --- a/llarp/iwp_link.cpp +++ b/llarp/iwp_link.cpp @@ -1396,8 +1396,8 @@ namespace iwp llarp::Debug("removing session ", addr); UnmapAddr(addr); session *s = static_cast< session * >(itr->second.impl); - m_sessions.erase(itr); s->done(); + m_sessions.erase(itr); if(s->frames) { llarp::Warn("session has ", s->frames, @@ -1903,18 +1903,19 @@ namespace iwp self->establish_job_id = 0; 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()) { - self->establish_job->session = self->parent; + job->session = self->parent; } else { // timer timeout - self->establish_job->session = nullptr; + job->session = nullptr; } - self->establish_job->result(self->establish_job); - self->establish_job = nullptr; + job->result(job); } } @@ -1950,22 +1951,23 @@ namespace iwp } } // namespace iwp -extern "C" { -void -iwp_link_init(struct llarp_link *link, struct llarp_iwp_args args) +extern "C" { - link->impl = iwp::link_alloc(args.router, args.keyfile, args.crypto, - args.logic, args.cryptoworker); - link->name = iwp::link_name; - link->get_our_address = iwp::link_get_addr; - link->configure = iwp::link_configure; - link->start_link = iwp::link_start; - link->stop_link = iwp::link_stop; - link->iter_sessions = iwp::link_iter_sessions; - link->try_establish = iwp::link_try_establish; - 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; -} + void + iwp_link_init(struct llarp_link *link, struct llarp_iwp_args args) + { + link->impl = iwp::link_alloc(args.router, args.keyfile, args.crypto, + args.logic, args.cryptoworker); + link->name = iwp::link_name; + link->get_our_address = iwp::link_get_addr; + link->configure = iwp::link_configure; + link->start_link = iwp::link_start; + link->stop_link = iwp::link_stop; + link->iter_sessions = iwp::link_iter_sessions; + link->try_establish = iwp::link_try_establish; + 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; + } } diff --git a/llarp/path.cpp b/llarp/path.cpp index 767a372eb..432c2a3f2 100644 --- a/llarp/path.cpp +++ b/llarp/path.cpp @@ -1,6 +1,7 @@ #include #include #include +#include "buffer.hpp" #include "router.hpp" namespace llarp @@ -69,6 +70,20 @@ namespace llarp } 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 > bool @@ -93,6 +108,21 @@ namespace llarp 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 PathContext::AddOwnPath(Path* path) { @@ -102,9 +132,22 @@ namespace llarp bool PathContext::HasTransitHop(const TransitHopInfo& info) { - return MapHas( - m_TransitPaths, info.pathID, - [info](const TransitHop& hop) -> bool { return info == hop.info; }); + return MapHas(m_TransitPaths, info.pathID, [info](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* @@ -113,10 +156,17 @@ namespace llarp return m_Router->pubkey(); } + llarp_router* + PathContext::Router() + { + return m_Router; + } + 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 @@ -126,45 +176,110 @@ namespace llarp auto now = llarp_time_now_ms(); auto& map = m_TransitPaths.second; auto itr = map.begin(); + std::set< TransitHop* > removePaths; while(itr != map.end()) { - if(itr->second.Expired(now)) - itr = map.erase(itr); - else - ++itr; + if(itr->second->Expired(now)) + { + TransitHop* path = itr->second; + llarp::Info("transit path expired ", path); + removePaths.insert(path); + } + ++itr; + } + for(auto& p : removePaths) + { + map.erase(p->info.txID); + map.erase(p->info.rxID); + delete p; } } + 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 - 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, - const LR_CommitRecord& record) - : pathID(record.pathid), upstream(record.nextHop), downstream(down) + bool + Path::Expired(llarp_time_t now) const { + 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& - Path::PathID() const + bool + Path::HandleRoutingMessage(llarp_buffer_t buf, llarp_router* r) { - return hops[0].pathID; + // TODO: implement me + return true; } - RouterID - Path::Upstream() + bool + 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 \ No newline at end of file diff --git a/llarp/path_confirm.cpp b/llarp/path_confirm.cpp new file mode 100644 index 000000000..11d549083 --- /dev/null +++ b/llarp/path_confirm.cpp @@ -0,0 +1,41 @@ +#include +#include +#include + +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 \ No newline at end of file diff --git a/llarp/pathbuilder.cpp b/llarp/pathbuilder.cpp index d470511a9..56689599c 100644 --- a/llarp/pathbuilder.cpp +++ b/llarp/pathbuilder.cpp @@ -47,8 +47,6 @@ namespace llarp abort(); return; } - // randomize hop's path id - hop.pathID.Randomize(); ++ctx->idx; diff --git a/llarp/relay_commit.cpp b/llarp/relay_commit.cpp index 68ae6fb02..bbe0469dd 100644 --- a/llarp/relay_commit.cpp +++ b/llarp/relay_commit.cpp @@ -1,5 +1,7 @@ #include +#include #include +#include "buffer.hpp" #include "logger.hpp" #include "router.hpp" @@ -73,7 +75,9 @@ namespace llarp return false; if(!BEncodeWriteDictEntry("n", tunnelNonce, buf)) return false; - if(!BEncodeWriteDictEntry("p", pathid, buf)) + if(!BEncodeWriteDictEntry("r", rxid, buf)) + return false; + if(!BEncodeWriteDictEntry("t", txid, buf)) return false; if(!bencode_write_version_entry(buf)) return false; @@ -106,7 +110,9 @@ namespace llarp if(!BEncodeMaybeReadDictEntry("n", self->tunnelNonce, read, *key, r->buffer)) 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; if(!BEncodeMaybeReadVersion("v", self->version, LLARP_PROTO_VERSION, read, *key, r->buffer)) @@ -144,7 +150,7 @@ namespace llarp return false; } return nextHop == other.nextHop && commkey == other.commkey - && pathid == other.pathid; + && txid == other.txid && rxid == other.rxid; } struct LRCMFrameDecrypt @@ -156,15 +162,15 @@ namespace llarp // decrypted record LR_CommitRecord record; // the actual hop - TransitHop hop; + TransitHop* hop; LRCMFrameDecrypt(PathContext* ctx, Decrypter* dec, const LR_CommitMessage* commit) - : decrypter(dec), context(ctx) + : decrypter(dec), context(ctx), hop(new TransitHop) { for(const auto& f : commit->frames) frames.push_back(f); - hop.info.downstream = commit->remote; + hop->info.downstream = commit->remote; } ~LRCMFrameDecrypt() @@ -177,19 +183,26 @@ namespace llarp SendLRCM(void* 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; } 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 HandleDecrypted(llarp_buffer_t* buf, LRCMFrameDecrypt* self) { - auto& info = self->hop.info; + auto& info = self->hop->info; if(!buf) { llarp::Error("LRCM decrypt failed from ", info.downstream); @@ -206,7 +219,8 @@ namespace llarp return; } - info.pathID = self->record.pathid; + info.txID = self->record.txid; + info.rxID = self->record.rxid; info.upstream = self->record.nextHop; if(self->context->HasTransitHop(info)) { @@ -216,7 +230,7 @@ namespace llarp } // generate path key as we are in a worker thread auto DH = self->context->Crypto()->dh_server; - if(!DH(self->hop.pathKey, self->record.commkey, + if(!DH(self->hop->pathKey, self->record.commkey, self->context->EncryptionSecretKey(), self->record.tunnelNonce)) { llarp::Error("LRCM DH Failed ", info); @@ -229,12 +243,12 @@ namespace llarp { llarp::Info("LRCM extended lifetime by ", 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 - self->hop.started = llarp_time_now_ms(); - llarp::Info("Accepted ", self->hop.info); + self->hop->started = llarp_time_now_ms(); + llarp::Info("Accepted ", self->hop->info); self->context->PutTransitHop(self->hop); size_t sz = self->frames.front().size(); @@ -250,7 +264,7 @@ namespace llarp // we are the farthest hop llarp::Info("We are the farthest hop for ", info); // send a LRAM down the path - llarp_logic_queue_job(self->context->Logic(), {self, &SendLRAM}); + llarp_logic_queue_job(self->context->Logic(), {self, &SendPathConfirm}); } else { diff --git a/llarp/relay_up_down.cpp b/llarp/relay_up_down.cpp index 4fb964999..e45fb24ac 100644 --- a/llarp/relay_up_down.cpp +++ b/llarp/relay_up_down.cpp @@ -1,5 +1,8 @@ +#include #include +#include "router.hpp" + namespace llarp { RelayUpstreamMessage::RelayUpstreamMessage(const RouterID &from) @@ -7,6 +10,10 @@ namespace llarp { } + RelayUpstreamMessage::RelayUpstreamMessage() : ILinkMessage() + { + } + RelayUpstreamMessage::~RelayUpstreamMessage() { } @@ -35,25 +42,62 @@ namespace llarp { } + RelayDownstreamMessage::RelayDownstreamMessage() : ILinkMessage() + { + } + RelayDownstreamMessage::~RelayDownstreamMessage() { } bool RelayDownstreamMessage::BEncode(llarp_buffer_t *buf) const { - // TODO: implement me - return false; + if(!bencode_start_dict(buf)) + 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 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 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; } -} +} // namespace llarp diff --git a/llarp/router.cpp b/llarp/router.cpp index b0493291c..d94568fa1 100644 --- a/llarp/router.cpp +++ b/llarp/router.cpp @@ -54,7 +54,7 @@ llarp_router::HandleRecvLinkMessage(llarp_link_session *session, bool llarp_router::SendToOrQueue(const llarp::RouterID &remote, - llarp::ILinkMessage *msg) + const llarp::ILinkMessage *msg) { llarp_link *chosen = nullptr; if(!outboundLink->has_session_to(outboundLink, remote)) @@ -444,7 +444,7 @@ llarp_router::send_padded_message(llarp_link_session_iter *itr, } void -llarp_router::SendTo(llarp::RouterID remote, llarp::ILinkMessage *msg, +llarp_router::SendTo(llarp::RouterID remote, const llarp::ILinkMessage *msg, llarp_link *link) { llarp_buffer_t buf = diff --git a/llarp/router.hpp b/llarp/router.hpp index 81bbe31f0..0c7cdb9b9 100644 --- a/llarp/router.hpp +++ b/llarp/router.hpp @@ -77,7 +77,7 @@ struct llarp_router llarp_link *outboundLink = nullptr; std::list< llarp_link * > inboundLinks; - typedef std::queue< llarp::ILinkMessage * > MessageQueue; + typedef std::queue< const llarp::ILinkMessage * > MessageQueue; /// outbound message queue std::map< llarp::RouterID, MessageQueue > outboundMesssageQueue; @@ -142,11 +142,11 @@ struct llarp_router /// NOT threadsafe /// MUST be called in the logic thread bool - SendToOrQueue(const llarp::RouterID &remote, llarp::ILinkMessage *msg); + SendToOrQueue(const llarp::RouterID &remote, const llarp::ILinkMessage *msg); /// sendto or drop void - SendTo(llarp::RouterID remote, llarp::ILinkMessage *msg, + SendTo(llarp::RouterID remote, const llarp::ILinkMessage *msg, llarp_link *chosen = nullptr); /// manually flush outbound message queue for just 1 router diff --git a/llarp/transit_hop.cpp b/llarp/transit_hop.cpp new file mode 100644 index 000000000..7870273c1 --- /dev/null +++ b/llarp/transit_hop.cpp @@ -0,0 +1,84 @@ +#include +#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 \ No newline at end of file diff --git a/test/encrypted_frame_unittest.cpp b/test/encrypted_frame_unittest.cpp index 9d737f87d..78b565545 100644 --- a/test/encrypted_frame_unittest.cpp +++ b/test/encrypted_frame_unittest.cpp @@ -43,7 +43,8 @@ TEST_F(FrameTest, TestFrameCrypto) LRCR record; record.nextHop.Fill(1); record.tunnelNonce.Fill(2); - record.pathid.Fill(3); + record.rxid.Fill(3); + record.txid.Fill(4); auto buf = f.Buffer(); buf->cur = buf->base + EncryptedFrame::OverheadSize;