From 2f8cde8e07231ae2f08325142629605070c22a71 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 22 Jun 2018 08:45:46 -0400 Subject: [PATCH 1/5] path building works in downstream direction --- include/llarp/aligned.hpp | 6 ++++ include/llarp/path.hpp | 7 +++-- llarp/path.cpp | 62 ++++++++++++++++++++++++++------------- llarp/pathbuilder.cpp | 3 +- llarp/relay_up_down.cpp | 6 ++-- llarp/transit_hop.cpp | 12 +++++--- 6 files changed, 65 insertions(+), 31 deletions(-) diff --git a/include/llarp/aligned.hpp b/include/llarp/aligned.hpp index 9cb7d84a9..e69baef2c 100644 --- a/include/llarp/aligned.hpp +++ b/include/llarp/aligned.hpp @@ -58,6 +58,12 @@ namespace llarp return !(*this == other); } + bool + operator<(const AlignedBuffer& other) const + { + return memcmp(l, other.l, sz) < 0; + } + size_t size() const { diff --git a/include/llarp/path.hpp b/include/llarp/path.hpp index 77f3c067f..1cb11cd4e 100644 --- a/include/llarp/path.hpp +++ b/include/llarp/path.hpp @@ -200,7 +200,10 @@ namespace llarp HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r); const PathID_t& - PathID() const; + TXID() const; + + const PathID_t& + RXID() const; RouterID Upstream() const; @@ -243,7 +246,7 @@ namespace llarp GetByUpstream(const RouterID& id, const PathID_t& path); IHopHandler* - GetDownstream(const RouterID& id, const PathID_t& path); + GetByDownstream(const RouterID& id, const PathID_t& path); bool ForwardLRCM(const RouterID& nextHop, std::deque< EncryptedFrame >& frames); diff --git a/llarp/path.cpp b/llarp/path.cpp index 432c2a3f2..926ce94ff 100644 --- a/llarp/path.cpp +++ b/llarp/path.cpp @@ -75,12 +75,11 @@ namespace llarp 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()) + auto range = map.second.equal_range(k); + for(auto i = range.first; i != range.second; ++i) { - if(check(itr->second)) - return itr->second; - ++itr; + if(check(i->second)) + return i->second; } return nullptr; } @@ -90,12 +89,11 @@ namespace llarp MapHas(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()) + auto range = map.second.equal_range(k); + for(auto i = range.first; i != range.second; ++i) { - if(check(itr->second)) + if(check(i->second)) return true; - ++itr; } return false; } @@ -108,31 +106,41 @@ namespace llarp map.second.emplace(k, v); } + template < typename Map_t, typename Visit_t > + void + MapIter(Map_t& map, Visit_t v) + { + std::unique_lock< std::mutex > lock(map.first); + for(const auto& item : map.second) + v(item); + } + 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()) + auto range = map.second.equal_range(k); + for(auto i = range.first; i != range.second;) { - if(check(itr->second)) - itr = map.second.erase(itr); + if(check(i->second)) + i = map.second.erase(i); else - ++itr; + ++i; } } void PathContext::AddOwnPath(Path* path) { - MapPut(m_OurPaths, path->PathID(), path); + MapPut(m_OurPaths, path->TXID(), path); + MapPut(m_OurPaths, path->RXID(), path); } bool PathContext::HasTransitHop(const TransitHopInfo& info) { - return MapHas(m_TransitPaths, info.pathID, [info](TransitHop* hop) -> bool { + return MapHas(m_TransitPaths, info.txID, [info](TransitHop* hop) -> bool { return info == hop->info; }); } @@ -145,11 +153,20 @@ namespace llarp }); if(own) return own; + return MapGet(m_TransitPaths, id, [remote](const TransitHop* hop) -> bool { return hop->info.upstream == remote; }); } + IHopHandler* + PathContext::GetByDownstream(const RouterID& remote, const PathID_t& id) + { + return MapGet(m_TransitPaths, id, [remote](const TransitHop* hop) -> bool { + return hop->info.downstream == remote; + }); + } + const byte_t* PathContext::OurRouterID() const { @@ -200,19 +217,25 @@ namespace llarp for(size_t idx = 0; idx < h->numHops; ++idx) { llarp_rc_copy(&hops[idx].router, &h->hops[idx].router); + hops[idx].txID.Randomize(); + hops[idx].rxID.Randomize(); + } + for(size_t idx = (h->numHops - 1); idx > 0; --idx) + { + hops[idx].txID = hops[idx - 1].rxID; } } const PathID_t& Path::TXID() const { - return hops[0].pathTX; + return hops[0].txID; } const PathID_t& Path::RXID() const { - return hops[0].pathRX; + return hops[0].rxID; } RouterID @@ -232,8 +255,7 @@ namespace llarp RelayUpstreamMessage* msg = new RelayUpstreamMessage; msg->X = buf; msg->Y = Y; - msg->pathid = PathID(); - msg->pathid.data_l()[1] = 0; + msg->pathid = TXID(); return r->SendToOrQueue(Upstream(), msg); } diff --git a/llarp/pathbuilder.cpp b/llarp/pathbuilder.cpp index 007c3c3bc..d807d90d9 100644 --- a/llarp/pathbuilder.cpp +++ b/llarp/pathbuilder.cpp @@ -64,7 +64,8 @@ namespace llarp // build record LR_CommitRecord record; record.version = LLARP_PROTO_VERSION; - record.pathid = hop.pathID; + record.txid = hop.txID; + record.rxid = hop.rxID; record.tunnelNonce = hop.nonce; record.nextHop = hop.upstream; record.commkey = llarp::seckey_topublic(hop.commkey); diff --git a/llarp/relay_up_down.cpp b/llarp/relay_up_down.cpp index e45fb24ac..704eae244 100644 --- a/llarp/relay_up_down.cpp +++ b/llarp/relay_up_down.cpp @@ -87,16 +87,14 @@ namespace llarp bool RelayDownstreamMessage::HandleMessage(llarp_router *router) const { - PathID_t id = pathid; - id.data_l()[0] = 0; - auto path = router->paths.GetByUpstream(remote, id); + auto path = router->paths.GetByUpstream(remote, pathid); if(path) { return path->HandleDownstream(X.Buffer(), Y, router); } else { - llarp::Warn("No such path upstream=", remote, " pathid=", id); + llarp::Warn("No such path upstream=", remote, " pathid=", pathid); } return false; } diff --git a/llarp/transit_hop.cpp b/llarp/transit_hop.cpp index 7870273c1..46636576d 100644 --- a/llarp/transit_hop.cpp +++ b/llarp/transit_hop.cpp @@ -11,7 +11,8 @@ namespace llarp } TransitHopInfo::TransitHopInfo(const TransitHopInfo& other) - : pathID(other.pathID) + : txID(other.txID) + , rxID(other.rxID) , upstream(other.upstream) , downstream(other.downstream) { @@ -19,7 +20,10 @@ namespace llarp TransitHopInfo::TransitHopInfo(const RouterID& down, const LR_CommitRecord& record) - : pathID(record.pathid), upstream(record.nextHop), downstream(down) + : txID(record.txid) + , rxID(record.rxid) + , upstream(record.nextHop) + , downstream(down) { } @@ -56,7 +60,7 @@ namespace llarp llarp_router* r) { RelayDownstreamMessage* msg = new RelayDownstreamMessage; - msg->pathid = info.rxID; + msg->pathid = info.txID; msg->Y = Y; r->crypto.xchacha20(buf, pathKey, Y); @@ -71,7 +75,7 @@ namespace llarp llarp_router* r) { RelayUpstreamMessage* msg = new RelayUpstreamMessage; - msg->pathid = info.txID; + msg->pathid = info.rxID; msg->Y = Y; r->crypto.xchacha20(buf, pathKey, Y); From f2c42e4e5af18ade49c1c20f3906eec912c2a383 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 22 Jun 2018 09:59:28 -0400 Subject: [PATCH 2/5] onion routing downstream traffic relaying works on testnet --- CMakeLists.txt | 3 +- Makefile | 2 +- include/llarp/bencode.hpp | 17 +++ include/llarp/crypto.h | 2 +- include/llarp/messages/path_confirm.hpp | 9 +- include/llarp/path.hpp | 8 +- include/llarp/routing/handler.hpp | 14 ++ include/llarp/routing/message.hpp | 46 ++++++ include/llarp/routing_message.hpp | 30 ---- llarp/iwp_link.cpp | 2 +- llarp/nodedb.cpp | 191 ++++++++++++------------ llarp/path.cpp | 15 +- llarp/pathbuilder.cpp | 3 +- llarp/routing/message_parser.cpp | 69 +++++++++ llarp/{ => routing}/path_confirm.cpp | 26 +++- 15 files changed, 286 insertions(+), 151 deletions(-) create mode 100644 include/llarp/routing/handler.hpp create mode 100644 include/llarp/routing/message.hpp delete mode 100644 include/llarp/routing_message.hpp create mode 100644 llarp/routing/message_parser.cpp rename llarp/{ => routing}/path_confirm.cpp (55%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 84bfd3a0e..fd5147e99 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,7 +124,6 @@ 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 @@ -136,6 +135,8 @@ set(LIB_SRC llarp/testnet.c llarp/time.cpp llarp/timer.cpp + llarp/routing/message_parser.cpp + llarp/routing/path_confirm.cpp vendor/cppbackport-master/lib/fs/rename.cpp vendor/cppbackport-master/lib/fs/filestatus.cpp vendor/cppbackport-master/lib/fs/filetype.cpp diff --git a/Makefile b/Makefile index c29f178eb..bd837db2d 100644 --- a/Makefile +++ b/Makefile @@ -66,7 +66,7 @@ testnet-build: testnet-configure testnet: testnet-build mkdir -p $(TESTNET_ROOT) - python3 contrib/testnet/genconf.py --bin=$(REPO)/llarpd --svc=30 --clients=300 --dir=$(TESTNET_ROOT) --out $(TESTNET_CONF) + python3 contrib/testnet/genconf.py --bin=$(REPO)/llarpd --svc=30 --clients=1 --dir=$(TESTNET_ROOT) --out $(TESTNET_CONF) supervisord -n -d $(TESTNET_ROOT) -l $(TESTNET_LOG) -c $(TESTNET_CONF) test: debug-configure diff --git a/include/llarp/bencode.hpp b/include/llarp/bencode.hpp index f07d1483e..fe9f5da54 100644 --- a/include/llarp/bencode.hpp +++ b/include/llarp/bencode.hpp @@ -48,6 +48,23 @@ namespace llarp return true; } + template < typename Int_t > + bool + BEncodeMaybeReadDictInt(const char* k, Int_t& i, bool& read, + llarp_buffer_t key, llarp_buffer_t* buf) + { + if(llarp_buffer_eq(key, k)) + { + if(!bencode_read_integer(buf, &i)) + { + llarp::Warn("failed to decode key ", k); + return false; + } + read = true; + } + return true; + } + template < typename Item_t > bool BEncodeMaybeReadVersion(const char* k, Item_t& item, uint64_t expect, diff --git a/include/llarp/crypto.h b/include/llarp/crypto.h index e3bfd8c1f..6e3282149 100644 --- a/include/llarp/crypto.h +++ b/include/llarp/crypto.h @@ -46,7 +46,7 @@ typedef byte_t llarp_tunnel_nonce_t[TUNNONCESIZE]; /// PKE(result, publickey, secretkey, nonce) typedef bool (*llarp_path_dh_func)(byte_t *, byte_t *, byte_t *, byte_t *); -/// TKE(result publickey, secretkey, nonce) +/// TKE(result, publickey, secretkey, nonce) typedef bool (*llarp_transport_dh_func)(byte_t *, byte_t *, byte_t *, byte_t *); /// SD/SE(buffer, key, nonce) diff --git a/include/llarp/messages/path_confirm.hpp b/include/llarp/messages/path_confirm.hpp index 6ada84510..d025cc4d0 100644 --- a/include/llarp/messages/path_confirm.hpp +++ b/include/llarp/messages/path_confirm.hpp @@ -1,7 +1,7 @@ #ifndef LLARP_MESSAGE_PATH_CONFIRM_HPP #define LLARP_MESSAGE_PATH_CONFIRM_HPP -#include +#include namespace llarp { @@ -11,18 +11,21 @@ namespace llarp { uint64_t pathLifetime; uint64_t pathCreated; - + PathConfirmMessage(); PathConfirmMessage(uint64_t lifetime); ~PathConfirmMessage(){}; bool BEncode(llarp_buffer_t* buf) const; + bool + DecodeKey(llarp_buffer_t key, llarp_buffer_t* val); + bool BDecode(llarp_buffer_t* buf); bool - HandleMessage(llarp_router* r) const; + HandleMessage(IMessageHandler* h) const; }; } // namespace routing } // namespace llarp diff --git a/include/llarp/path.hpp b/include/llarp/path.hpp index 1cb11cd4e..85255ba39 100644 --- a/include/llarp/path.hpp +++ b/include/llarp/path.hpp @@ -10,7 +10,8 @@ #include #include #include -#include +#include +#include #include #include @@ -173,7 +174,7 @@ namespace llarp }; /// A path we made - struct Path : public IHopHandler + struct Path : public IHopHandler, public llarp::routing::IMessageHandler { typedef std::vector< PathHopConfig > HopList; HopList hops; @@ -207,6 +208,9 @@ namespace llarp RouterID Upstream() const; + + protected: + llarp::routing::InboundMessageParser m_InboundMessageParser; }; enum PathBuildStatus diff --git a/include/llarp/routing/handler.hpp b/include/llarp/routing/handler.hpp new file mode 100644 index 000000000..950f60205 --- /dev/null +++ b/include/llarp/routing/handler.hpp @@ -0,0 +1,14 @@ +#ifndef LLARP_ROUTING_HANDLER_HPP +#define LLARP_ROUTING_HANDLER_HPP + +namespace llarp +{ + namespace routing + { + struct IMessageHandler + { + }; + } // namespace routing +} // namespace llarp + +#endif \ No newline at end of file diff --git a/include/llarp/routing/message.hpp b/include/llarp/routing/message.hpp new file mode 100644 index 000000000..3e9d98bf0 --- /dev/null +++ b/include/llarp/routing/message.hpp @@ -0,0 +1,46 @@ +#ifndef LLARP_ROUTING_MESSAGE_HPP +#define LLARP_ROUTING_MESSAGE_HPP + +#include +#include +#include + +namespace llarp +{ + namespace routing + { + struct IMessageHandler; + + struct IMessage + { + llarp::PathID_t from; + + virtual ~IMessage(){}; + + virtual bool + BEncode(llarp_buffer_t* buf) const = 0; + + virtual bool + DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) = 0; + + virtual bool + HandleMessage(IMessageHandler* r) const = 0; + }; + + struct InboundMessageParser + { + InboundMessageParser(); + bool + ParseMessageBuffer(llarp_buffer_t buf, IMessageHandler* handler); + + private: + static bool + OnKey(dict_reader* r, llarp_buffer_t* key); + bool firstKey; + dict_reader reader; + IMessage* msg; + }; + } // namespace routing +} // namespace llarp + +#endif \ No newline at end of file diff --git a/include/llarp/routing_message.hpp b/include/llarp/routing_message.hpp deleted file mode 100644 index dd29344bc..000000000 --- a/include/llarp/routing_message.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#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/iwp_link.cpp b/llarp/iwp_link.cpp index 68693dcef..8cb212e06 100644 --- a/llarp/iwp_link.cpp +++ b/llarp/iwp_link.cpp @@ -1397,7 +1397,7 @@ namespace iwp UnmapAddr(addr); session *s = static_cast< session * >(itr->second.impl); s->done(); - m_sessions.erase(itr); + m_sessions.erase(addr); if(s->frames) { llarp::Warn("session has ", s->frames, diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index 8b7ae3dd3..a4ff86d95 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -291,127 +291,128 @@ nodedb_async_load_rc(void *user) llarp_logic_queue_job(job->logic, {job, &nodedb_inform_load_rc}); } -extern "C" { -struct llarp_nodedb * -llarp_nodedb_new(struct llarp_crypto *crypto) +extern "C" { - return new llarp_nodedb(crypto); -} - -void -llarp_nodedb_free(struct llarp_nodedb **n) -{ - if(*n) + struct llarp_nodedb * + llarp_nodedb_new(struct llarp_crypto *crypto) { - auto i = *n; - *n = nullptr; - i->Clear(); - delete i; + return new llarp_nodedb(crypto); } -} - -bool -llarp_nodedb_ensure_dir(const char *dir) -{ - fs::path path(dir); - std::error_code ec; - if(!fs::exists(dir, ec)) - fs::create_directories(path, ec); - - if(ec) - return false; - if(!fs::is_directory(path)) - return false; + void + llarp_nodedb_free(struct llarp_nodedb **n) + { + if(*n) + { + auto i = *n; + *n = nullptr; + i->Clear(); + delete i; + } + } - for(const char &ch : skiplist_subdirs) + bool + llarp_nodedb_ensure_dir(const char *dir) { - std::string p; - p += ch; - fs::path sub = path / p; - fs::create_directory(sub, ec); + fs::path path(dir); + std::error_code ec; + if(!fs::exists(dir, ec)) + fs::create_directories(path, ec); + if(ec) return false; + + if(!fs::is_directory(path)) + return false; + + for(const char &ch : skiplist_subdirs) + { + std::string p; + p += ch; + fs::path sub = path / p; + fs::create_directory(sub, ec); + if(ec) + return false; + } + return true; } - return true; -} -ssize_t -llarp_nodedb_load_dir(struct llarp_nodedb *n, const char *dir) -{ - std::error_code ec; - if(!fs::exists(dir, ec)) + ssize_t + llarp_nodedb_load_dir(struct llarp_nodedb *n, const char *dir) { - return -1; + std::error_code ec; + if(!fs::exists(dir, ec)) + { + return -1; + } + n->nodePath = dir; + return n->Load(dir); } - n->nodePath = dir; - return n->Load(dir); -} - -void -llarp_nodedb_async_verify(struct llarp_async_verify_rc *job) -{ - // switch to crypto threadpool and continue with - // crypto_threadworker_verifyrc - llarp_threadpool_queue_job(job->cryptoworker, - {job, &crypto_threadworker_verifyrc}); -} -void -llarp_nodedb_async_load_rc(struct llarp_async_load_rc *job) -{ - // call in the disk io thread so we don't bog down the others - llarp_threadpool_queue_job(job->diskworker, {job, &nodedb_async_load_rc}); -} + void + llarp_nodedb_async_verify(struct llarp_async_verify_rc *job) + { + // switch to crypto threadpool and continue with + // crypto_threadworker_verifyrc + llarp_threadpool_queue_job(job->cryptoworker, + {job, &crypto_threadworker_verifyrc}); + } -struct llarp_rc * -llarp_nodedb_get_rc(struct llarp_nodedb *n, const byte_t *pk) -{ - if(n->Has(pk)) - return n->getRC(pk); - else - return nullptr; -} + void + llarp_nodedb_async_load_rc(struct llarp_async_load_rc *job) + { + // call in the disk io thread so we don't bog down the others + llarp_threadpool_queue_job(job->diskworker, {job, &nodedb_async_load_rc}); + } -size_t -llarp_nodedb_num_loaded(struct llarp_nodedb *n) -{ - return n->entries.size(); -} + struct llarp_rc * + llarp_nodedb_get_rc(struct llarp_nodedb *n, const byte_t *pk) + { + if(n->Has(pk)) + return n->getRC(pk); + else + return nullptr; + } -void -llarp_nodedb_select_random_hop(struct llarp_nodedb *n, struct llarp_rc *prev, - struct llarp_rc *result, size_t N) -{ - /// TODO: check for "guard" status for N = 0? - auto sz = n->entries.size(); + size_t + llarp_nodedb_num_loaded(struct llarp_nodedb *n) + { + return n->entries.size(); + } - if(prev) + void + llarp_nodedb_select_random_hop(struct llarp_nodedb *n, struct llarp_rc *prev, + struct llarp_rc *result, size_t N) { - do + /// TODO: check for "guard" status for N = 0? + auto sz = n->entries.size(); + + if(prev) + { + do + { + auto itr = n->entries.begin(); + if(sz > 1) + { + auto idx = rand() % sz; + std::advance(itr, idx); + } + if(memcmp(prev->pubkey, itr->second.pubkey, PUBKEYSIZE) == 0) + continue; + llarp_rc_copy(result, &itr->second); + return; + } while(true); + } + else { auto itr = n->entries.begin(); if(sz > 1) { - auto idx = rand() % (sz - 1); + auto idx = rand() % sz; std::advance(itr, idx); } - if(memcmp(prev->pubkey, itr->second.pubkey, PUBKEYSIZE) == 0) - continue; llarp_rc_copy(result, &itr->second); - return; - } while(true); - } - else - { - auto itr = n->entries.begin(); - if(sz > 1) - { - auto idx = rand() % (sz - 1); - std::advance(itr, idx); } - llarp_rc_copy(result, &itr->second); } -} } // end extern diff --git a/llarp/path.cpp b/llarp/path.cpp index 926ce94ff..46cf37928 100644 --- a/llarp/path.cpp +++ b/llarp/path.cpp @@ -269,14 +269,9 @@ namespace llarp Path::HandleDownstream(llarp_buffer_t buf, const TunnelNonce& Y, llarp_router* r) { - size_t idx = hops.size() - 1; - while(idx >= 0) + for(const auto& hop : hops) { - r->crypto.xchacha20(buf, hops[idx].shared, Y); - if(idx) - idx--; - else - break; + r->crypto.xchacha20(buf, hop.shared, Y); } return HandleRoutingMessage(buf, r); } @@ -284,7 +279,11 @@ namespace llarp bool Path::HandleRoutingMessage(llarp_buffer_t buf, llarp_router* r) { - // TODO: implement me + if(!m_InboundMessageParser.ParseMessageBuffer(buf, this)) + { + llarp::Warn("Failed to parse inbound routing message"); + return false; + } return true; } diff --git a/llarp/pathbuilder.cpp b/llarp/pathbuilder.cpp index d807d90d9..027bb2f33 100644 --- a/llarp/pathbuilder.cpp +++ b/llarp/pathbuilder.cpp @@ -47,10 +47,9 @@ namespace llarp abort(); return; } - ++ctx->idx; - bool isFarthestHop = ctx->idx == ctx->path->hops.size() - 1; + bool isFarthestHop = ctx->idx == ctx->path->hops.size(); if(isFarthestHop) { diff --git a/llarp/routing/message_parser.cpp b/llarp/routing/message_parser.cpp new file mode 100644 index 000000000..90a4e4f82 --- /dev/null +++ b/llarp/routing/message_parser.cpp @@ -0,0 +1,69 @@ +#include +#include + +namespace llarp +{ + namespace routing + { + InboundMessageParser::InboundMessageParser() + { + reader.user = this; + reader.on_key = &OnKey; + firstKey = false; + } + + bool + InboundMessageParser::OnKey(dict_reader* r, llarp_buffer_t* key) + { + InboundMessageParser* self = + static_cast< InboundMessageParser* >(r->user); + + if(key == nullptr && self->firstKey) + { + // empty dict + return false; + } + if(!key) + return true; + if(self->firstKey) + { + llarp_buffer_t strbuf; + if(!llarp_buffer_eq(*key, "A")) + return false; + if(!bencode_read_string(r->buffer, &strbuf)) + return false; + if(strbuf.sz != 1) + return false; + switch(*strbuf.cur) + { + case 'P': + self->msg = new PathConfirmMessage; + break; + default: + llarp::Error("invalid routing message id: ", *strbuf.cur); + } + self->firstKey = false; + return self->msg != nullptr; + } + else + { + return self->msg->DecodeKey(*key, r->buffer); + } + } + + bool + InboundMessageParser::ParseMessageBuffer(llarp_buffer_t buf, + IMessageHandler* h) + { + bool result = false; + msg = nullptr; + firstKey = true; + if(bencode_read_dict(&buf, &reader)) + { + result = msg->HandleMessage(h); + delete msg; + } + return result; + } + } // namespace routing +} // namespace llarp \ No newline at end of file diff --git a/llarp/path_confirm.cpp b/llarp/routing/path_confirm.cpp similarity index 55% rename from llarp/path_confirm.cpp rename to llarp/routing/path_confirm.cpp index 11d549083..c2263d8d4 100644 --- a/llarp/path_confirm.cpp +++ b/llarp/routing/path_confirm.cpp @@ -1,16 +1,32 @@ #include #include #include +#include namespace llarp { namespace routing { + PathConfirmMessage::PathConfirmMessage() : pathLifetime(0), pathCreated(0) + { + } + PathConfirmMessage::PathConfirmMessage(uint64_t lifetime) : pathLifetime(lifetime), pathCreated(llarp_time_now_ms()) { } + bool + PathConfirmMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t* val) + { + bool read = false; + if(!BEncodeMaybeReadDictInt("L", pathLifetime, read, key, val)) + return false; + if(!BEncodeMaybeReadDictInt("S", pathCreated, read, key, val)) + return false; + return read; + } + bool PathConfirmMessage::BEncode(llarp_buffer_t* buf) const { @@ -26,14 +42,10 @@ namespace llarp } bool - PathConfirmMessage::BDecode(llarp_buffer_t* buf) - { - return false; - } - - bool - PathConfirmMessage::HandleMessage(llarp_router* r) const + PathConfirmMessage::HandleMessage(IMessageHandler* h) const { + llarp::Info("got path confirm created=", pathCreated, + " lifetime=", pathLifetime); return true; } From 47b4b5c5366c898d926824f8fc0966a066bfe63a Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 22 Jun 2018 09:59:50 -0400 Subject: [PATCH 3/5] make format --- llarp/nodedb.cpp | 189 +++++++++++++++++++++++------------------------ 1 file changed, 94 insertions(+), 95 deletions(-) diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index a4ff86d95..77ec9efed 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -291,119 +291,104 @@ nodedb_async_load_rc(void *user) llarp_logic_queue_job(job->logic, {job, &nodedb_inform_load_rc}); } -extern "C" +extern "C" { +struct llarp_nodedb * +llarp_nodedb_new(struct llarp_crypto *crypto) { - struct llarp_nodedb * - llarp_nodedb_new(struct llarp_crypto *crypto) - { - return new llarp_nodedb(crypto); - } + return new llarp_nodedb(crypto); +} - void - llarp_nodedb_free(struct llarp_nodedb **n) +void +llarp_nodedb_free(struct llarp_nodedb **n) +{ + if(*n) { - if(*n) - { - auto i = *n; - *n = nullptr; - i->Clear(); - delete i; - } + auto i = *n; + *n = nullptr; + i->Clear(); + delete i; } +} - bool - llarp_nodedb_ensure_dir(const char *dir) - { - fs::path path(dir); - std::error_code ec; - if(!fs::exists(dir, ec)) - fs::create_directories(path, ec); - - if(ec) - return false; +bool +llarp_nodedb_ensure_dir(const char *dir) +{ + fs::path path(dir); + std::error_code ec; + if(!fs::exists(dir, ec)) + fs::create_directories(path, ec); - if(!fs::is_directory(path)) - return false; + if(ec) + return false; - for(const char &ch : skiplist_subdirs) - { - std::string p; - p += ch; - fs::path sub = path / p; - fs::create_directory(sub, ec); - if(ec) - return false; - } - return true; - } + if(!fs::is_directory(path)) + return false; - ssize_t - llarp_nodedb_load_dir(struct llarp_nodedb *n, const char *dir) + for(const char &ch : skiplist_subdirs) { - std::error_code ec; - if(!fs::exists(dir, ec)) - { - return -1; - } - n->nodePath = dir; - return n->Load(dir); + std::string p; + p += ch; + fs::path sub = path / p; + fs::create_directory(sub, ec); + if(ec) + return false; } + return true; +} - void - llarp_nodedb_async_verify(struct llarp_async_verify_rc *job) +ssize_t +llarp_nodedb_load_dir(struct llarp_nodedb *n, const char *dir) +{ + std::error_code ec; + if(!fs::exists(dir, ec)) { - // switch to crypto threadpool and continue with - // crypto_threadworker_verifyrc - llarp_threadpool_queue_job(job->cryptoworker, - {job, &crypto_threadworker_verifyrc}); + return -1; } + n->nodePath = dir; + return n->Load(dir); +} - void - llarp_nodedb_async_load_rc(struct llarp_async_load_rc *job) - { - // call in the disk io thread so we don't bog down the others - llarp_threadpool_queue_job(job->diskworker, {job, &nodedb_async_load_rc}); - } +void +llarp_nodedb_async_verify(struct llarp_async_verify_rc *job) +{ + // switch to crypto threadpool and continue with + // crypto_threadworker_verifyrc + llarp_threadpool_queue_job(job->cryptoworker, + {job, &crypto_threadworker_verifyrc}); +} - struct llarp_rc * - llarp_nodedb_get_rc(struct llarp_nodedb *n, const byte_t *pk) - { - if(n->Has(pk)) - return n->getRC(pk); - else - return nullptr; - } +void +llarp_nodedb_async_load_rc(struct llarp_async_load_rc *job) +{ + // call in the disk io thread so we don't bog down the others + llarp_threadpool_queue_job(job->diskworker, {job, &nodedb_async_load_rc}); +} - size_t - llarp_nodedb_num_loaded(struct llarp_nodedb *n) - { - return n->entries.size(); - } +struct llarp_rc * +llarp_nodedb_get_rc(struct llarp_nodedb *n, const byte_t *pk) +{ + if(n->Has(pk)) + return n->getRC(pk); + else + return nullptr; +} - void - llarp_nodedb_select_random_hop(struct llarp_nodedb *n, struct llarp_rc *prev, - struct llarp_rc *result, size_t N) - { - /// TODO: check for "guard" status for N = 0? - auto sz = n->entries.size(); +size_t +llarp_nodedb_num_loaded(struct llarp_nodedb *n) +{ + return n->entries.size(); +} - if(prev) - { - do - { - auto itr = n->entries.begin(); - if(sz > 1) - { - auto idx = rand() % sz; - std::advance(itr, idx); - } - if(memcmp(prev->pubkey, itr->second.pubkey, PUBKEYSIZE) == 0) - continue; - llarp_rc_copy(result, &itr->second); - return; - } while(true); - } - else +void +llarp_nodedb_select_random_hop(struct llarp_nodedb *n, struct llarp_rc *prev, + struct llarp_rc *result, size_t N) +{ + /// TODO: check for "guard" status for N = 0? + auto sz = n->entries.size(); + + if(prev) + { + do { auto itr = n->entries.begin(); if(sz > 1) @@ -411,8 +396,22 @@ extern "C" auto idx = rand() % sz; std::advance(itr, idx); } + if(memcmp(prev->pubkey, itr->second.pubkey, PUBKEYSIZE) == 0) + continue; llarp_rc_copy(result, &itr->second); + return; + } while(true); + } + else + { + auto itr = n->entries.begin(); + if(sz > 1) + { + auto idx = rand() % sz; + std::advance(itr, idx); } + llarp_rc_copy(result, &itr->second); } +} } // end extern From 65233617ac9ece58ed7142e79da68e4df95f87af Mon Sep 17 00:00:00 2001 From: Jeff Date: Fri, 22 Jun 2018 16:13:56 -0400 Subject: [PATCH 4/5] fix macos build --- llarp/router.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llarp/router.cpp b/llarp/router.cpp index d94568fa1..50cfb78f4 100644 --- a/llarp/router.cpp +++ b/llarp/router.cpp @@ -650,13 +650,13 @@ llarp_router::Run() // initialize as service node InitServiceNode(); // immediate connect all for service node - auto delay = rand() % 100; + uint64_t delay = rand() % 100; llarp_logic_call_later(logic, {delay, this, &ConnectAll}); } else { // delayed connect all for clients - auto delay = ((rand() % 10) * 500) + 1000; + uint64_t delay = ((rand() % 10) * 500) + 1000; llarp_logic_call_later(logic, {delay, this, &ConnectAll}); } From c88d3860b829a17a5496fed80d97df9bc4c982ea Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 22 Jun 2018 20:00:44 -0400 Subject: [PATCH 5/5] some api code --- CMakeLists.txt | 15 ++- client/main.cpp | 15 +++ doc/proto_v0.txt | 13 +-- include/llarp/api.hpp | 14 +++ include/llarp/api/client.hpp | 29 +++++ include/llarp/api/messages.hpp | 125 ++++++++++++++++++++ include/llarp/api/parser.hpp | 26 +++++ include/llarp/api/server.hpp | 29 +++++ include/llarp/bencode.hpp | 36 ++++++ include/llarp/link_message.hpp | 14 +-- include/llarp/messages/path_latency.hpp | 28 +++++ include/llarp/path.hpp | 3 + include/llarp/routing/handler.hpp | 5 + include/llarp/routing/message.hpp | 11 +- include/llarp/service.hpp | 57 ++++++++++ include/llarp/service_info.h | 28 ----- llarp/api/client.cpp | 145 ++++++++++++++++++++++++ llarp/api/create_session.cpp | 18 +++ llarp/api/message.cpp | 109 ++++++++++++++++++ llarp/api/parser.cpp | 60 ++++++++++ llarp/path.cpp | 7 ++ llarp/routing/path_latency.cpp | 11 ++ llarp/service.cpp | 1 + test/api_unittest.cpp | 27 +++++ 24 files changed, 768 insertions(+), 58 deletions(-) create mode 100644 client/main.cpp create mode 100644 include/llarp/api.hpp create mode 100644 include/llarp/api/client.hpp create mode 100644 include/llarp/api/messages.hpp create mode 100644 include/llarp/api/parser.hpp create mode 100644 include/llarp/api/server.hpp create mode 100644 include/llarp/messages/path_latency.hpp create mode 100644 include/llarp/service.hpp delete mode 100644 include/llarp/service_info.h create mode 100644 llarp/api/client.cpp create mode 100644 llarp/api/create_session.cpp create mode 100644 llarp/api/message.cpp create mode 100644 llarp/api/parser.cpp create mode 100644 llarp/routing/path_latency.cpp create mode 100644 llarp/service.cpp create mode 100644 test/api_unittest.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index fd5147e99..ea3ecfc88 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,6 +135,10 @@ set(LIB_SRC llarp/testnet.c llarp/time.cpp llarp/timer.cpp + llarp/api/create_session.cpp + llarp/api/client.cpp + llarp/api/message.cpp + llarp/api/parser.cpp llarp/routing/message_parser.cpp llarp/routing/path_confirm.cpp vendor/cppbackport-master/lib/fs/rename.cpp @@ -157,12 +161,19 @@ set(LIB_SRC set(TEST_SRC test/main.cpp + test/api_unittest.cpp test/dht_unittest.cpp test/encrypted_frame_unittest.cpp ) set(TEST_EXE testAll) set(GTEST_DIR test/gtest) +set(CLIENT_EXE llarpc) + +set(CLIENT_SRC + client/main.cpp +) + # TODO: exclude this from includes and expose stuff properly for rcutil include_directories(llarp) @@ -179,7 +190,8 @@ else() add_executable(rcutil daemon/rcutil.cpp) add_executable(${EXE} ${EXE_SRC}) - + add_executable(${CLIENT_EXE} ${CLIENT_SRC}) + if(WITH_TESTS) enable_testing() add_subdirectory(${GTEST_DIR}) @@ -195,6 +207,7 @@ else() if(NOT WITH_SHARED) target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB}) target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB}) + target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB}) endif() endif() diff --git a/client/main.cpp b/client/main.cpp new file mode 100644 index 000000000..c9a2c81a2 --- /dev/null +++ b/client/main.cpp @@ -0,0 +1,15 @@ +#include + +int +main(int argc, char* argv[]) +{ + std::string url = llarp::api::DefaultURL; + if(argc > 1) + { + url = argv[1]; + } + llarp::api::Client cl; + if(!cl.Start(url)) + return 1; + return cl.Mainloop(); +} \ No newline at end of file diff --git a/doc/proto_v0.txt b/doc/proto_v0.txt index dccb5b0a3..3f2f77e0a 100644 --- a/doc/proto_v0.txt +++ b/doc/proto_v0.txt @@ -137,14 +137,13 @@ s is the long term public signing key v is the protocol version x is a nounce value for generating vanity addresses that can be omitted -if x is included it MUST be less than or equal to 16 bytes, any larger and it is -considered invalid. +if x is included it MUST be equal to 16 bytes { e: "<32 bytes public encryption key>", s: "<32 bytes public signing key>", v: 0, - x: "" + x: "" } service address (SA) @@ -314,10 +313,6 @@ h = HS(BE(w)) h has log_e(y) prefix of 0x00 -y = 2 means prefix of 0x00 -y = 4 means prefix of 0x00 0x00 -y = 32 means prefix 0x00 0x00 0x00 0x00 0x00 - this proof of work requirement is subject to change if i is equal to RC.k then any LRDM.x values are decrypted and interpreted as @@ -345,7 +340,7 @@ otherwise transmit a LRUM to the next hop p: p, v: 0, x: x1, - y: HS(y) + y: y } link relay downstream message (LRDM) @@ -542,7 +537,7 @@ transfer data between paths. P: "<16 bytes path id>", T: "", V: 0, - Y: "<32 bytes nounce>", + Y: "<32 bytes nounce>" } transfer data to another path with id P on the local router place Y and T values diff --git a/include/llarp/api.hpp b/include/llarp/api.hpp new file mode 100644 index 000000000..189e01755 --- /dev/null +++ b/include/llarp/api.hpp @@ -0,0 +1,14 @@ +#ifndef LLARP_API_HPP +#define LLARP_API_HPP + +#include +#include +namespace llarp +{ + namespace api + { + const char DefaultURL[] = "127.0.0.1:34567"; + } +} // namespace llarp + +#endif \ No newline at end of file diff --git a/include/llarp/api/client.hpp b/include/llarp/api/client.hpp new file mode 100644 index 000000000..2bbd08e53 --- /dev/null +++ b/include/llarp/api/client.hpp @@ -0,0 +1,29 @@ +#ifndef LLARP_API_CLIENT_HPP +#define LLARP_API_CLIENT_HPP + +#include + +namespace llarp +{ + namespace api + { + struct ClientPImpl; + + struct Client + { + Client(); + ~Client(); + + bool + Start(const std::string& apiURL); + + int + Mainloop(); + + private: + ClientPImpl* m_Impl; + }; + + } // namespace api +} // namespace llarp +#endif \ No newline at end of file diff --git a/include/llarp/api/messages.hpp b/include/llarp/api/messages.hpp new file mode 100644 index 000000000..b817e68a4 --- /dev/null +++ b/include/llarp/api/messages.hpp @@ -0,0 +1,125 @@ +#ifndef LLARP_API_MESSAGES_HPP +#define LLARP_API_MESSAGES_HPP + +#include +#include +#include +#include + +namespace llarp +{ + namespace api + { + // forward declare + struct Client; + struct Server; + + /// base message + struct IMessage : public IBEncodeMessage + { + uint64_t sessionID = 0; + uint64_t msgID = 0; + uint64_t version = 0; + llarp::ShortHash hash; + + // the function name this message belongs to + virtual std::string + FunctionName() const = 0; + + bool + BEncode(llarp_buffer_t* buf) const; + + bool + DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf); + + virtual std::list< IBEncodeMessage* > + GetParams() const = 0; + + virtual bool + DecodeParams(llarp_buffer_t* buf) = 0; + + bool + IsWellFormed(llarp_crypto* c, const std::string& password); + + void + CalculateHash(llarp_crypto* c, const std::string& password); + }; + + /// a "yes we got your command" type message + struct AcknoledgeMessage : public IMessage + { + }; + + /// start a session with the router + struct CreateSessionMessage : public IMessage + { + std::list< IBEncodeMessage* > + GetParams() const + { + return {}; + } + + bool + DecodeParams(llarp_buffer_t* buf); + + std::string + FunctionName() const + { + return "CreateSession"; + } + }; + + /// a keepalive ping + struct SessionPingMessage : public IMessage + { + }; + + /// end a session with the router + struct DestroySessionMessage : public IMessage + { + }; + + /// base messgae type for hidden service control and transmission + struct HSMessage : public IMessage + { + llarp::PubKey pubkey; + llarp::Signature sig; + + /// validate signature on message (server side) + bool + SignatureIsValid(llarp_crypto* crypto) const; + + /// sign message using secret key (client side) + bool + SignMessge(llarp_crypto* crypto, byte_t* seckey); + }; + + /// create a new hidden service + struct CreateServiceMessgae : public HSMessage + { + }; + + /// end an already created hidden service we created + struct DestroyServiceMessage : public HSMessage + { + }; + + /// start lookup of another service's descriptor + struct LookupServiceMessage : public IMessage + { + }; + + /// publish our hidden service's descriptor + struct PublishServiceMessage : public IMessage + { + }; + + /// send pre encrypted data down a path we own + struct SendPathDataMessage : public IMessage + { + }; + + } // namespace api +} // namespace llarp + +#endif \ No newline at end of file diff --git a/include/llarp/api/parser.hpp b/include/llarp/api/parser.hpp new file mode 100644 index 000000000..4879fde20 --- /dev/null +++ b/include/llarp/api/parser.hpp @@ -0,0 +1,26 @@ +#ifndef LLARP_API_PARSER_HPP +#define LLARP_API_PARSER_HPP +#include +#include + +namespace llarp +{ + namespace api + { + struct MessageParser + { + MessageParser(); + + IMessage * + ParseMessage(llarp_buffer_t buf); + + private: + static bool + OnKey(dict_reader *r, llarp_buffer_t *key); + IMessage *msg = nullptr; + dict_reader r; + }; + } // namespace api +} // namespace llarp + +#endif \ No newline at end of file diff --git a/include/llarp/api/server.hpp b/include/llarp/api/server.hpp new file mode 100644 index 000000000..3732a47b8 --- /dev/null +++ b/include/llarp/api/server.hpp @@ -0,0 +1,29 @@ +#ifndef LLARP_API_SERVER_HPP +#define LLARP_API_SERVER_HPP + +#include +#include +#include + +namespace llarp +{ + namespace api + { + struct ServerPImpl; + + struct Server + { + Server(llarp_router* r); + ~Server(); + + bool + Bind(const std::string& url, llarp_ev_loop* loop); + + private: + ServerPImpl* m_Impl; + }; + + } // namespace api +} // namespace llarp + +#endif \ No newline at end of file diff --git a/include/llarp/bencode.hpp b/include/llarp/bencode.hpp index fe9f5da54..e3e24c4d4 100644 --- a/include/llarp/bencode.hpp +++ b/include/llarp/bencode.hpp @@ -12,6 +12,13 @@ namespace llarp return bencode_write_bytestring(buf, k, 1) && bencode_write_bytestring(buf, t, 1); } + template < typename Obj_t > + bool + BEncodeWriteDictString(const char* k, const Obj_t& str, llarp_buffer_t* buf) + { + return bencode_write_bytestring(buf, k, 1) + && bencode_write_bytestring(buf, str.c_str(), str.size()); + } template < typename Obj_t > bool @@ -79,6 +86,22 @@ namespace llarp return true; } + template < typename List_t > + bool + BEncodeWriteDictBEncodeList(const char* k, const List_t& l, + llarp_buffer_t* buf) + { + if(!bencode_write_bytestring(buf, k, 1)) + return false; + if(!bencode_start_list(buf)) + return false; + + for(const auto& item : l) + if(!item->BEncode(buf)) + return false; + return bencode_end(buf); + } + template < typename Iter > bool BEncodeWriteList(Iter itr, Iter end, llarp_buffer_t* buf) @@ -119,6 +142,19 @@ namespace llarp return bencode_write_bytestring(buf, k, 1) && BEncodeWriteList(list.begin(), list.end(), buf); } + + /// bencode serializable message + struct IBEncodeMessage + { + virtual ~IBEncodeMessage(){}; + + virtual bool + DecodeKey(llarp_buffer_t key, llarp_buffer_t* val) = 0; + + virtual bool + BEncode(llarp_buffer_t* buf) const = 0; + }; + } // namespace llarp #endif \ No newline at end of file diff --git a/include/llarp/link_message.hpp b/include/llarp/link_message.hpp index 6bcd8977b..279bef2a6 100644 --- a/include/llarp/link_message.hpp +++ b/include/llarp/link_message.hpp @@ -1,8 +1,8 @@ #ifndef LLARP_LINK_MESSAGE_HPP #define LLARP_LINK_MESSAGE_HPP -#include #include +#include #include #include @@ -15,7 +15,7 @@ namespace llarp typedef std::queue< ILinkMessage* > SendQueue; /// parsed link layer message - struct ILinkMessage + struct ILinkMessage : public IBEncodeMessage { /// who did this message come from (rc.k) RouterID remote = {}; @@ -24,14 +24,6 @@ namespace llarp ILinkMessage() = default; ILinkMessage(const RouterID& id); - virtual ~ILinkMessage(){}; - - virtual bool - DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) = 0; - - virtual bool - BEncode(llarp_buffer_t* buf) const = 0; - virtual bool HandleMessage(llarp_router* router) const = 0; }; @@ -63,6 +55,6 @@ namespace llarp llarp_link_session* from; ILinkMessage* msg = nullptr; }; -} +} // namespace llarp #endif diff --git a/include/llarp/messages/path_latency.hpp b/include/llarp/messages/path_latency.hpp new file mode 100644 index 000000000..8eb077d31 --- /dev/null +++ b/include/llarp/messages/path_latency.hpp @@ -0,0 +1,28 @@ +#ifndef LLARP_MESSAGES_PATH_LATENCY_HPP +#define LLARP_MESSAGES_PATH_LATENCY_HPP + +#include + +namespace llarp +{ + namespace routing + { + struct PathLatencyMessage : public IMessage + { + uint64_t T = 0; + uint64_t L = 0; + PathLatencyMessage(); + + bool + BEncode(llarp_buffer_t* buf) const; + + bool + DecodeKey(llarp_buffer_t key, llarp_buffer_t* val); + + bool + HandleMessage(IMessageHandler* r) const; + }; + } // namespace routing +} // namespace llarp + +#endif \ No newline at end of file diff --git a/include/llarp/path.hpp b/include/llarp/path.hpp index 85255ba39..20b602c57 100644 --- a/include/llarp/path.hpp +++ b/include/llarp/path.hpp @@ -192,6 +192,9 @@ namespace llarp bool HandleRoutingMessage(llarp_buffer_t buf, llarp_router* r); + bool + HandleHiddenServiceData(llarp_buffer_t buf); + // handle data in upstream direction bool HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r); diff --git a/include/llarp/routing/handler.hpp b/include/llarp/routing/handler.hpp index 950f60205..15a3e1f63 100644 --- a/include/llarp/routing/handler.hpp +++ b/include/llarp/routing/handler.hpp @@ -1,12 +1,17 @@ #ifndef LLARP_ROUTING_HANDLER_HPP #define LLARP_ROUTING_HANDLER_HPP +#include + namespace llarp { namespace routing { + // handles messages on owned paths struct IMessageHandler { + virtual bool + HandleHiddenServiceData(llarp_buffer_t buf) = 0; }; } // namespace routing } // namespace llarp diff --git a/include/llarp/routing/message.hpp b/include/llarp/routing/message.hpp index 3e9d98bf0..4fb0a9197 100644 --- a/include/llarp/routing/message.hpp +++ b/include/llarp/routing/message.hpp @@ -3,6 +3,7 @@ #include #include +#include #include namespace llarp @@ -11,18 +12,10 @@ namespace llarp { struct IMessageHandler; - struct IMessage + struct IMessage : public llarp::IBEncodeMessage { llarp::PathID_t from; - virtual ~IMessage(){}; - - virtual bool - BEncode(llarp_buffer_t* buf) const = 0; - - virtual bool - DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) = 0; - virtual bool HandleMessage(IMessageHandler* r) const = 0; }; diff --git a/include/llarp/service.hpp b/include/llarp/service.hpp new file mode 100644 index 000000000..88fed137a --- /dev/null +++ b/include/llarp/service.hpp @@ -0,0 +1,57 @@ +#ifndef LLARP_SERVICE_HPP +#define LLARP_SERVICE_HPP +#include +#include +#include + +namespace llarp +{ + namespace service + { + /// hidden service address + typedef llarp::AlignedBuffer< 32 > Address; + + typedef llarp::AlignedBuffer< 16 > VanityNonce; + + struct Info : public llarp::IBEncodeMessage + { + llarp::PubKey enckey; + llarp::PubKey signkey; + uint64_t version = 0; + VanityNonce vanity; + + /// calculate our address + void + CalculateAddress(llarp_crypto* c, Address& addr) const; + + bool + BEncode(llarp_buffer_t* buf) const; + + bool + DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf); + }; + + // private keys + struct Identity : public llarp::IBEncodeMessage + { + llarp::SecretKey enckey; + llarp::SecretKey signkey; + uint64_t version = 0; + VanityNonce vanity; + + // public service info + Info pub; + + // regenerate secret keys + void + RegenerateKeys(llarp_crypto* c); + + // load from file + bool + LoadFromFile(const std::string& fpath); + }; + + }; // namespace service +} // namespace llarp + +#endif \ No newline at end of file diff --git a/include/llarp/service_info.h b/include/llarp/service_info.h deleted file mode 100644 index e0a38c568..000000000 --- a/include/llarp/service_info.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef LLARP_SI_H -#define LLARP_SI_H -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct llarp_service_info -{ - llarp_buffer_t name; - llarp_pubkey_t signingkey; - llarp_buffer_t vanity; -}; - -void -llarp_service_info_hash(struct llarp_service_info *si, llarp_hash_t *h); -bool -llarp_service_info_bencode(struct llarp_serivce_info *si, llarp_buffer_t *buff); -bool -llarp_service_info_bdecode(struct llarp_serivce_info *si, llarp_buffer_t buff); -void -llarp_service_info_free(struct llarp_service_info **si); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/llarp/api/client.cpp b/llarp/api/client.cpp new file mode 100644 index 000000000..c212d09bf --- /dev/null +++ b/llarp/api/client.cpp @@ -0,0 +1,145 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace llarp +{ + namespace api + { + struct ClientPImpl + { + ClientPImpl() + { + llarp_ev_loop_alloc(&loop); + worker = llarp_init_same_process_threadpool(); + logic = llarp_init_single_process_logic(worker); + } + + ~ClientPImpl() + { + llarp_ev_loop_free(&loop); + } + + static void + HandleRecv(llarp_udp_io* u, const sockaddr* from, const void* buf, + ssize_t sz) + { + static_cast< ClientPImpl* >(u->user)->RecvFrom(from, buf, sz); + } + + void + RecvFrom(const sockaddr* from, const void* b, ssize_t sz) + { + if(from->sa_family != AF_INET + || ((sockaddr_in*)from)->sin_addr.s_addr != apiAddr.sin_addr.s_addr + || ((sockaddr_in*)from)->sin_port != apiAddr.sin_port) + { + // address missmatch + llarp::Warn("got packet from bad address"); + return; + } + llarp_buffer_t buf; + buf.base = (byte_t*)b; + buf.cur = buf.base; + buf.sz = sz; + IMessage* msg = m_MessageParser.ParseMessage(buf); + if(msg) + { + delete msg; + } + else + llarp::Warn("Got Invalid Message"); + } + + bool + BindDefault() + { + ouraddr.sin_family = AF_INET; + ouraddr.sin_addr.s_addr = INADDR_LOOPBACK; + ouraddr.sin_port = 0; + udp.user = this; + udp.recvfrom = &HandleRecv; + return llarp_ev_add_udp(loop, &udp, (const sockaddr*)&ouraddr) != -1; + } + + bool + StartSession(const std::string& addr, uint16_t port) + { + apiAddr.sin_family = AF_INET; + if(inet_pton(AF_INET, addr.c_str(), &apiAddr.sin_addr.s_addr) == -1) + return false; + apiAddr.sin_port = htons(port); + CreateSessionMessage msg; + return SendMessage(&msg); + } + + bool + SendMessage(const IMessage* msg) + { + llarp_buffer_t buf; + byte_t tmp[1500]; + buf.base = tmp; + buf.cur = buf.base; + buf.sz = sizeof(tmp); + if(msg->BEncode(&buf)) + return llarp_ev_udp_sendto(&udp, (const sockaddr*)&apiAddr, buf.base, + buf.sz) + != -1; + return false; + } + + int + Mainloop() + { + llarp_ev_loop_run_single_process(loop, worker, logic); + return 0; + } + llarp_threadpool* worker; + llarp_logic* logic; + llarp_ev_loop* loop; + sockaddr_in ouraddr; + sockaddr_in apiAddr; + llarp_udp_io udp; + MessageParser m_MessageParser; + }; + + Client::Client() : m_Impl(new ClientPImpl) + { + } + + Client::~Client() + { + delete m_Impl; + } + + bool + Client::Start(const std::string& url) + { + if(url.find(":") == std::string::npos) + return false; + if(!m_Impl->BindDefault()) + return false; + std::string addr = url.substr(0, url.find(":")); + std::string strport = url.substr(url.find(":") + 1); + int port = std::stoi(strport); + if(port == -1) + return false; + return m_Impl->StartSession(addr, port); + } + + int + Client::Mainloop() + { + return m_Impl->Mainloop(); + } + + } // namespace api +} // namespace llarp \ No newline at end of file diff --git a/llarp/api/create_session.cpp b/llarp/api/create_session.cpp new file mode 100644 index 000000000..c1d62b79f --- /dev/null +++ b/llarp/api/create_session.cpp @@ -0,0 +1,18 @@ +#include +#include +#include +#include + +namespace llarp +{ + namespace api + { + + bool + CreateSessionMessage::DecodeParams(llarp_buffer_t *buf) + { + std::list< llarp::Encrypted > params; + return BEncodeReadList(params, buf); + } + } // namespace api +} // namespace llarp \ No newline at end of file diff --git a/llarp/api/message.cpp b/llarp/api/message.cpp new file mode 100644 index 000000000..977731216 --- /dev/null +++ b/llarp/api/message.cpp @@ -0,0 +1,109 @@ +#include + +namespace llarp +{ + namespace api + { + bool + IMessage::BEncode(llarp_buffer_t* buf) const + { + if(!bencode_start_dict(buf)) + return false; + if(!BEncodeWriteDictString("F", FunctionName(), buf)) + return false; + if(!BEncodeWriteDictInt(buf, "I", sessionID)) + return false; + if(!BEncodeWriteDictInt(buf, "M", msgID)) + return false; + if(!BEncodeWriteDictBEncodeList("P", GetParams(), buf)) + return false; + if(!BEncodeWriteDictEntry("Z", hash, buf)) + return false; + return bencode_end(buf); + } + + bool + IMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t* val) + { + if(llarp_buffer_eq(key, "P")) + { + return DecodeParams(val); + } + bool read = false; + if(!BEncodeMaybeReadDictInt("I", sessionID, read, key, val)) + return false; + if(!BEncodeMaybeReadDictInt("M", msgID, read, key, val)) + return false; + if(!BEncodeMaybeReadDictEntry("Z", hash, read, key, val)) + return false; + return read; + } + + bool + IMessage::IsWellFormed(llarp_crypto* crypto, const std::string& password) + { + // hash password + llarp::ShortHash secret; + llarp_buffer_t passbuf; + passbuf.base = (byte_t*)password.c_str(); + passbuf.cur = passbuf.base; + passbuf.sz = password.size(); + crypto->shorthash(secret, passbuf); + + llarp::ShortHash digest, tmpHash; + // save hash + tmpHash = hash; + // zero hash + hash.Zero(); + + // bencode + byte_t tmp[1500]; + llarp_buffer_t buf; + buf.base = tmp; + buf.cur = buf.base; + buf.sz = sizeof(tmp); + if(!BEncode(&buf)) + return false; + + // rewind buffer + buf.sz = buf.cur - buf.base; + buf.cur = buf.base; + // calculate message auth + crypto->hmac(digest, buf, secret); + // restore hash + hash = tmpHash; + return tmpHash == digest; + } + + void + IMessage::CalculateHash(llarp_crypto* crypto, const std::string& password) + { + // hash password + llarp::ShortHash secret; + llarp_buffer_t passbuf; + passbuf.base = (byte_t*)password.c_str(); + passbuf.cur = passbuf.base; + passbuf.sz = password.size(); + crypto->shorthash(secret, passbuf); + + llarp::ShortHash digest; + // zero hash + hash.Zero(); + + // bencode + byte_t tmp[1500]; + llarp_buffer_t buf; + buf.base = tmp; + buf.cur = buf.base; + buf.sz = sizeof(tmp); + if(BEncode(&buf)) + { + // rewind buffer + buf.sz = buf.cur - buf.base; + buf.cur = buf.base; + // calculate message auth + crypto->hmac(hash, buf, secret); + } + } + } // namespace api +} // namespace llarp \ No newline at end of file diff --git a/llarp/api/parser.cpp b/llarp/api/parser.cpp new file mode 100644 index 000000000..7eaf7b249 --- /dev/null +++ b/llarp/api/parser.cpp @@ -0,0 +1,60 @@ +#include +#include +#include + +namespace llarp +{ + namespace api + { + std::map< std::string, std::function< IMessage*() > > funcmap = { + {"CreateSession", []() { return new CreateSessionMessage; }}, + }; + + MessageParser::MessageParser() + { + r.user = this; + r.on_key = &OnKey; + } + + bool + MessageParser::OnKey(dict_reader* r, llarp_buffer_t* key) + { + MessageParser* self = static_cast< MessageParser* >(r->user); + if(self->msg == nullptr && key == nullptr) // empty message + return false; + if(self->msg == nullptr && key) + { + // first message, function name + if(!llarp_buffer_eq(*key, "f")) + return false; + llarp_buffer_t strbuf; + if(!bencode_read_string(r->buffer, &strbuf)) + return false; + std::string funcname((char*)strbuf.cur, strbuf.sz); + auto itr = funcmap.find(funcname); + if(itr == funcmap.end()) + return false; + self->msg = itr->second(); + return true; + } + else if(self->msg && key) + { + return self->msg->DecodeKey(*key, r->buffer); + } + else if(self->msg && key == nullptr) + { + return true; + } + return false; + } + + IMessage* + MessageParser::ParseMessage(llarp_buffer_t buf) + { + if(bencode_read_dict(&buf, &r)) + return msg; + return nullptr; + } + + } // namespace api +} // namespace llarp \ No newline at end of file diff --git a/llarp/path.cpp b/llarp/path.cpp index 46cf37928..c1a8b320c 100644 --- a/llarp/path.cpp +++ b/llarp/path.cpp @@ -276,6 +276,13 @@ namespace llarp return HandleRoutingMessage(buf, r); } + bool + Path::HandleHiddenServiceData(llarp_buffer_t buf) + { + // TODO: implement me + return false; + } + bool Path::HandleRoutingMessage(llarp_buffer_t buf, llarp_router* r) { diff --git a/llarp/routing/path_latency.cpp b/llarp/routing/path_latency.cpp new file mode 100644 index 000000000..d1c427706 --- /dev/null +++ b/llarp/routing/path_latency.cpp @@ -0,0 +1,11 @@ +#include + +namespace llarp +{ + namespace routing + { + PathLatencyMessage::PathLatencyMessage() + { + } + } // namespace routing +} // namespace llarp \ No newline at end of file diff --git a/llarp/service.cpp b/llarp/service.cpp new file mode 100644 index 000000000..49f5b1764 --- /dev/null +++ b/llarp/service.cpp @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/test/api_unittest.cpp b/test/api_unittest.cpp new file mode 100644 index 000000000..5dfec6ee4 --- /dev/null +++ b/test/api_unittest.cpp @@ -0,0 +1,27 @@ +#include +#include + +class APITest : public ::testing::Test +{ + public: + llarp_crypto crypto; + std::string apiPassword = "password"; + APITest() + { + llarp_crypto_libsodium_init(&crypto); + } + + ~APITest() + { + } +}; + +TEST_F(APITest, TestMessageWellFormed) +{ + llarp::api::CreateSessionMessage msg; + msg.msgID = 0; + msg.sessionID = 12345; + msg.CalculateHash(&crypto, apiPassword); + llarp::Info("msghash=", msg.hash); + ASSERT_TRUE(msg.IsWellFormed(&crypto, apiPassword)); +}; \ No newline at end of file