diff --git a/.vscode/settings.json b/.vscode/settings.json index 139978ee1..f974c0315 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -54,6 +54,9 @@ "__config": "cpp", "__nullptr": "cpp", "algorithm": "cpp", - "io": "cpp" + "io": "cpp", + "strstream": "cpp", + "numeric": "cpp", + "valarray": "cpp" } } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 38e772388..91547410d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,6 +125,7 @@ set(LIB_SRC llarp/nodedb.cpp llarp/path.cpp llarp/pathbuilder.cpp + llarp/pathset.cpp llarp/proofofwork.cpp llarp/relay_ack.cpp llarp/relay_commit.cpp diff --git a/Makefile b/Makefile index bd837db2d..a8a3df515 100644 --- a/Makefile +++ b/Makefile @@ -59,14 +59,14 @@ shadow: shadow-build bash -c "$(SHADOW_BIN) -w $$(cat /proc/cpuinfo | grep processor | wc -l) $(SHADOW_CONFIG) &> $(SHADOW_LOG) || true" testnet-configure: clean - cmake -GNinja -DCMAKE_BUILD_TYPE=Debug + cmake -GNinja -DCMAKE_BUILD_TYPE=Debug testnet-build: testnet-configure ninja testnet: testnet-build mkdir -p $(TESTNET_ROOT) - python3 contrib/testnet/genconf.py --bin=$(REPO)/llarpd --svc=30 --clients=1 --dir=$(TESTNET_ROOT) --out $(TESTNET_CONF) + python3 contrib/testnet/genconf.py --bin=$(REPO)/llarpd --svc=30 --clients=300 --dir=$(TESTNET_ROOT) --out $(TESTNET_CONF) supervisord -n -d $(TESTNET_ROOT) -l $(TESTNET_LOG) -c $(TESTNET_CONF) test: debug-configure diff --git a/daemon/rcutil.cpp b/daemon/rcutil.cpp index e49d9963d..7f80cab49 100644 --- a/daemon/rcutil.cpp +++ b/daemon/rcutil.cpp @@ -21,21 +21,22 @@ handle_signal(int sig) #include #include #include -#include "fs.hpp" #include "buffer.hpp" #include "crypto.hpp" +#include "fs.hpp" #include "router.hpp" -bool printNode(struct llarp_nodedb_iter *iter) { +bool +printNode(struct llarp_nodedb_iter *iter) +{ char ftmp[68] = {0}; const char *hexname = - llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(iter->rc->pubkey, ftmp); + llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(iter->rc->pubkey, ftmp); printf("[%zu]=>[%s]\n", iter->index, hexname); return false; } - int main(int argc, char *argv[]) { @@ -61,9 +62,9 @@ main(int argc, char *argv[]) "\n"); return 0; } - bool genMode = false; - bool updMode = false; - bool listMode = false; + bool genMode = false; + bool updMode = false; + bool listMode = false; bool importMode = false; bool exportMode = false; int c; @@ -71,8 +72,8 @@ main(int argc, char *argv[]) char defaultConfName[] = "daemon.ini"; conffname = defaultConfName; char *rcfname; - char defaultRcName[] = "other.signed"; - rcfname = defaultRcName; + char defaultRcName[] = "other.signed"; + rcfname = defaultRcName; bool haveRequiredOptions = false; while(1) { @@ -97,49 +98,51 @@ main(int argc, char *argv[]) break; case 'l': haveRequiredOptions = true; - listMode = true; + listMode = true; break; case 'i': // printf ("option -g with value `%s'\n", optarg); - rcfname = optarg; + rcfname = optarg; haveRequiredOptions = true; - importMode = true; + importMode = true; break; case 'e': // printf ("option -g with value `%s'\n", optarg); - rcfname = optarg; + rcfname = optarg; haveRequiredOptions = true; - exportMode = true; + exportMode = true; break; case 'g': // printf ("option -g with value `%s'\n", optarg); - rcfname = optarg; + rcfname = optarg; haveRequiredOptions = true; - genMode = true; + genMode = true; break; case 'u': // printf ("option -u with value `%s'\n", optarg); - rcfname = optarg; + rcfname = optarg; haveRequiredOptions = true; - updMode = true; + updMode = true; break; default: abort(); } } - if (!haveRequiredOptions) { + if(!haveRequiredOptions) + { llarp::Error("Parameters dont all have their required parameters.\n"); return 0; } printf("parsed options\n"); - if(!genMode && !updMode && !listMode &&!importMode && !exportMode) + if(!genMode && !updMode && !listMode && !importMode && !exportMode) { llarp::Error("I don't know what to do, no generate or update parameter\n"); return 0; } ctx = llarp_main_init(conffname, !TESTNET); - if (!ctx) { + if(!ctx) + { llarp::Error("Cant set up context"); return 0; } @@ -162,10 +165,12 @@ main(int argc, char *argv[]) llarp_crypto crypt; llarp_crypto_libsodium_init(&crypt); - // which is in daemon.ini config: router.encryption-privkey (defaults "encryption.key") + // which is in daemon.ini config: router.encryption-privkey (defaults + // "encryption.key") fs::path encryption_keyfile = "encryption.key"; llarp::SecretKey encryption; - llarp_findOrCreateEncryption(&crypt, encryption_keyfile.c_str(), &encryption); + llarp_findOrCreateEncryption(&crypt, encryption_keyfile.c_str(), + &encryption); llarp_rc_set_pubenckey(&tmp, llarp::seckey_topublic(encryption)); // get identity public sig key @@ -206,33 +211,37 @@ main(int argc, char *argv[]) // write file llarp_rc_write(&tmp, our_rc_file_out.c_str()); } - if (listMode) { + if(listMode) + { llarp_main_loadDatabase(ctx); llarp_nodedb_iter iter; iter.visit = printNode; llarp_main_iterateDatabase(ctx, iter); } - if (importMode) { + if(importMode) + { llarp_main_loadDatabase(ctx); llarp::Info("Loading ", rcfname); llarp_rc *rc = llarp_rc_read(rcfname); - if (!rc) + if(!rc) { llarp::Error("Can't load RC"); return 0; } llarp_main_putDatabase(ctx, rc); } - if (exportMode) { + if(exportMode) + { llarp_main_loadDatabase(ctx); - //llarp::Info("Looking for string: ", rcfname); + // llarp::Info("Looking for string: ", rcfname); llarp::PubKey binaryPK; llarp::HexDecode(rcfname, binaryPK.data()); - + llarp::Info("Looking for binary: ", binaryPK); struct llarp_rc *rc = llarp_main_getDatabase(ctx, binaryPK.data()); - if (!rc) { + if(!rc) + { llarp::Error("Can't load RC from database"); } std::string filename(rcfname); @@ -241,5 +250,5 @@ main(int argc, char *argv[]) llarp_rc_write(rc, filename.c_str()); } llarp_main_free(ctx); - return 1; // success + return 1; // success } diff --git a/include/llarp.h b/include/llarp.h index 97d1f89af..b6913ddf0 100644 --- a/include/llarp.h +++ b/include/llarp.h @@ -39,7 +39,6 @@ llarp_main_loadDatabase(struct llarp_main *ptr); int llarp_main_iterateDatabase(struct llarp_main *ptr, struct llarp_nodedb_iter i); - /// put RC into nodeDB bool llarp_main_putDatabase(struct llarp_main *ptr, struct llarp_rc *rc); @@ -47,7 +46,6 @@ llarp_main_putDatabase(struct llarp_main *ptr, struct llarp_rc *rc); struct llarp_rc * llarp_main_getDatabase(struct llarp_main *ptr, byte_t *pk); - void llarp_main_free(struct llarp_main *ptr); diff --git a/include/llarp/aligned.hpp b/include/llarp/aligned.hpp index e69baef2c..c2acf0a0e 100644 --- a/include/llarp/aligned.hpp +++ b/include/llarp/aligned.hpp @@ -83,6 +83,14 @@ namespace llarp b[idx] = f; } + bool + IsZero() const + { + AlignedBuffer< sz > b; + b.Zero(); + return memcmp(l, b.l, sz) == 0; + } + void Zero() { diff --git a/include/llarp/crypto_async.h b/include/llarp/crypto_async.h index 773ac524c..f5f7f61cd 100644 --- a/include/llarp/crypto_async.h +++ b/include/llarp/crypto_async.h @@ -4,6 +4,7 @@ #include #include #include +#include /** * crypto_async.h @@ -166,6 +167,8 @@ struct iwp_async_frame { /// true if decryption succeded bool success; + /// timestamp for CoDel + llarp_time_t created; struct llarp_async_iwp *iwp; /// a pointer to pass ourself void *user; @@ -179,6 +182,14 @@ struct iwp_async_frame byte_t buf[1500]; }; +/// synchronously decrypt a frame +bool +iwp_decrypt_frame(struct iwp_async_frame *frame); + +/// synchronosuly encrypt a frame +bool +iwp_encrypt_frame(struct iwp_async_frame *frame); + /// decrypt iwp frame asynchronously void iwp_call_async_frame_decrypt(struct llarp_async_iwp *iwp, diff --git a/include/llarp/dht.hpp b/include/llarp/dht.hpp index 1df7e05ce..0bae9eeee 100644 --- a/include/llarp/dht.hpp +++ b/include/llarp/dht.hpp @@ -30,9 +30,6 @@ namespace llarp { } - bool - IsZero() const; - Key_t operator^(const Key_t& other) const { @@ -49,8 +46,6 @@ namespace llarp } }; - extern Key_t ZeroKey; - struct Node { llarp_rc* rc; diff --git a/include/llarp/encode.hpp b/include/llarp/encode.hpp index e3396a879..6232c8ad8 100644 --- a/include/llarp/encode.hpp +++ b/include/llarp/encode.hpp @@ -1,7 +1,7 @@ #ifndef LLARP_ENCODE_HPP #define LLARP_ENCODE_HPP -#include #include +#include namespace llarp { @@ -28,8 +28,10 @@ namespace llarp return &stack[0]; } - int char2int(char input); - void HexDecode(const char* src, uint8_t* target); + int + char2int(char input); + void + HexDecode(const char* src, uint8_t* target); } #endif diff --git a/include/llarp/messages/relay_commit.hpp b/include/llarp/messages/relay_commit.hpp index 8c58baac2..7e48c69d0 100644 --- a/include/llarp/messages/relay_commit.hpp +++ b/include/llarp/messages/relay_commit.hpp @@ -11,7 +11,10 @@ namespace llarp { // forward declare - struct PathContext; + namespace path + { + struct PathContext; + } struct LR_CommitRecord { @@ -67,7 +70,7 @@ namespace llarp HandleMessage(llarp_router *router) const; bool - AsyncDecrypt(PathContext *context) const; + AsyncDecrypt(llarp::path::PathContext *context) const; }; } // namespace llarp diff --git a/include/llarp/path.h b/include/llarp/path.h index 29522d220..dd7043047 100644 --- a/include/llarp/path.h +++ b/include/llarp/path.h @@ -4,6 +4,9 @@ #include #define MAXHOPS (8) +#define DEFAULT_PATH_LIFETIME (10 * 60 * 1000) +#define PATH_BUILD_TIMEOUT (30 * 1000) + #ifdef __cplusplus extern "C" { #endif diff --git a/include/llarp/path.hpp b/include/llarp/path.hpp index 1ed83cf66..02bb19abc 100644 --- a/include/llarp/path.hpp +++ b/include/llarp/path.hpp @@ -5,10 +5,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -19,292 +21,315 @@ #include #include -#define DEFAULT_PATH_LIFETIME (10 * 60 * 1000) - namespace llarp { - struct TransitHopInfo + namespace path { - TransitHopInfo() = default; - TransitHopInfo(const TransitHopInfo& other); - TransitHopInfo(const RouterID& down, const LR_CommitRecord& record); + struct TransitHopInfo + { + TransitHopInfo() = default; + TransitHopInfo(const TransitHopInfo& other); + TransitHopInfo(const RouterID& down, const LR_CommitRecord& record); - PathID_t txID, rxID; - RouterID upstream; - RouterID downstream; + PathID_t txID, rxID; + RouterID upstream; + RouterID downstream; - friend std::ostream& - operator<<(std::ostream& out, const TransitHopInfo& info) - { - out << ""; - } + friend std::ostream& + operator<<(std::ostream& out, const TransitHopInfo& info) + { + out << ""; + } - bool - operator==(const TransitHopInfo& other) const - { - return txID == other.txID && rxID == other.rxID - && upstream == other.upstream && downstream == other.downstream; - } + bool + operator==(const TransitHopInfo& other) const + { + return txID == other.txID && rxID == other.rxID + && upstream == other.upstream && downstream == other.downstream; + } - bool - operator!=(const TransitHopInfo& other) const - { - return !(*this == other); - } + bool + operator!=(const TransitHopInfo& other) const + { + return !(*this == other); + } - bool - operator<(const TransitHopInfo& other) const - { - return txID < other.txID || rxID < other.rxID || upstream < other.upstream - || downstream < other.downstream; - } + bool + operator<(const TransitHopInfo& other) const + { + return txID < other.txID || rxID < other.rxID + || upstream < other.upstream || downstream < other.downstream; + } + + struct Hash + { + std::size_t + operator()(TransitHopInfo const& a) const + { + 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.txID, sizeof(std::size_t)); + memcpy(&idx3, a.rxID, sizeof(std::size_t)); + return idx0 ^ idx1 ^ idx2; + } + }; + }; - struct Hash + struct PathIDHash { std::size_t - operator()(TransitHopInfo const& a) const + operator()(const PathID_t& a) const { - 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.txID, sizeof(std::size_t)); - memcpy(&idx3, a.rxID, sizeof(std::size_t)); - return idx0 ^ idx1 ^ idx2; + std::size_t idx0; + memcpy(&idx0, a, sizeof(std::size_t)); + return idx0; } }; - }; - struct PathIDHash - { - std::size_t - operator()(const PathID_t& a) const + struct IHopHandler { - std::size_t idx0; - memcpy(&idx0, a, sizeof(std::size_t)); - return idx0; - } - }; + virtual ~IHopHandler(){}; - 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; - virtual bool - Expired(llarp_time_t now) const = 0; + // handle data in upstream direction + virtual bool + HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y, + llarp_router* r) = 0; - virtual bool - SendRoutingMessage(const llarp::routing::IMessage* msg, + // handle data in downstream direction + virtual bool + HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r) = 0; + }; - // handle data in upstream direction - virtual bool - HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r) = 0; + struct TransitHop : public IHopHandler + { + TransitHop() = default; - // handle data in downstream direction - virtual bool - HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y, - llarp_router* r) = 0; - }; + TransitHop(const TransitHop& other); - struct TransitHop : public IHopHandler - { - TransitHop() = default; + TransitHopInfo info; + SharedSecret pathKey; + llarp_time_t started = 0; + // 10 minutes default + 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; - TransitHop(const TransitHop& other); + bool + SendRoutingMessage(const llarp::routing::IMessage* msg, llarp_router* r); - TransitHopInfo info; - SharedSecret pathKey; - llarp_time_t started = 0; - // 10 minutes default - llarp_time_t lifetime = DEFAULT_PATH_LIFETIME; - llarp_proto_version_t version; + // handle data in upstream direction + bool + HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r); - friend std::ostream& - operator<<(std::ostream& out, const TransitHop& h) + // 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 { - return out << "[TransitHop " << h.info << " started=" << h.started - << " lifetime=" << h.lifetime << "]"; - } + /// path id + PathID_t txID, rxID; + // router contact of router + llarp_rc router; + // temp public encryption key + SecretKey commkey; + /// shared secret at this hop + SharedSecret shared; + /// next hop's router id + RouterID upstream; + /// nonce for key exchange + TunnelNonce nonce; + // lifetime + llarp_time_t lifetime = DEFAULT_PATH_LIFETIME; + + ~PathHopConfig(); + PathHopConfig(); + }; - bool - Expired(llarp_time_t now) const; + /// A path we made + struct Path : public IHopHandler, public llarp::routing::IMessageHandler + { + typedef std::function< void(Path*) > BuildResultHookFunc; + typedef std::vector< PathHopConfig > HopList; + HopList hops; + llarp_time_t buildStarted; + PathStatus status; - bool - SendRoutingMessage(const llarp::routing::IMessage* msg, llarp_router* r); + Path(llarp_path_hops* path); - // handle data in upstream direction - bool - HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r); + void + SetBuildResultHook(BuildResultHookFunc func); - // handle data in downstream direction - bool - HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r); - }; + bool + Expired(llarp_time_t now) const; - /// configuration for a single hop when building a path - struct PathHopConfig - { - /// path id - PathID_t txID, rxID; - // router contact of router - llarp_rc router; - // temp public encryption key - SecretKey commkey; - /// shared secret at this hop - SharedSecret shared; - /// next hop's router id - RouterID upstream; - /// nonce for key exchange - TunnelNonce nonce; - // lifetime - llarp_time_t lifetime = DEFAULT_PATH_LIFETIME; - - ~PathHopConfig(); - PathHopConfig(); - }; - - enum PathStatus - { - ePathBuilding, - ePathEstablished, - ePathTimeout, - ePathExpired - }; - - /// A path we made - struct Path : public IHopHandler, public llarp::routing::IMessageHandler - { - typedef std::vector< PathHopConfig > HopList; - HopList hops; - llarp_time_t buildStarted; - PathStatus status; + bool + SendRoutingMessage(const llarp::routing::IMessage* msg, llarp_router* r); - Path(llarp_path_hops* path); + bool + HandlePathConfirmMessage(const llarp::routing::PathConfirmMessage* msg); - bool - Expired(llarp_time_t now) const; + bool + HandlePathLatencyMessage(const llarp::routing::PathLatencyMessage* msg); - bool - SendRoutingMessage(const llarp::routing::IMessage* msg, llarp_router* r); + bool + HandleDHTMessage(const llarp::dht::IMessage* msg); - bool - HandleRoutingMessage(llarp_buffer_t buf, llarp_router* r); + bool + HandleRoutingMessage(llarp_buffer_t buf, llarp_router* r); - bool - HandleHiddenServiceData(llarp_buffer_t buf); + bool + HandleHiddenServiceData(llarp_buffer_t buf); - // handle data in upstream direction - bool - HandleUpstream(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); + // handle data in downstream direction + bool + HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r); - // Is this deprecated? - const PathID_t& - TXID() const; + // Is this deprecated? + // nope not deprecated :^DDDD + const PathID_t& + TXID() const; - const PathID_t& - RXID() const; + const PathID_t& + RXID() const; - RouterID - Upstream() const; + RouterID + Upstream() const; - protected: - llarp::routing::InboundMessageParser m_InboundMessageParser; - }; + protected: + llarp::routing::InboundMessageParser m_InboundMessageParser; - enum PathBuildStatus - { - ePathBuildSuccess, - ePathBuildTimeout, - ePathBuildReject - }; + private: + BuildResultHookFunc m_BuiltHook; + }; - struct PathContext - { - PathContext(llarp_router* router); - ~PathContext(); + enum PathBuildStatus + { + ePathBuildSuccess, + ePathBuildTimeout, + ePathBuildReject + }; + + struct PathContext + { + PathContext(llarp_router* router); + ~PathContext(); - /// called from router tick function - void - ExpirePaths(); + /// called from router tick function + void + ExpirePaths(); - void - AllowTransit(); - void - RejectTransit(); + /// called from router tick function + /// builds all paths we need to build at current tick + void + BuildPaths(); - bool - AllowingTransit() const; + /// track a path builder with this context + void + AddPathBuilder(llarp_pathbuilder_context* set); - bool - HasTransitHop(const TransitHopInfo& info); + void + AllowTransit(); + void + RejectTransit(); - bool - HandleRelayCommit(const LR_CommitMessage* msg); + bool + AllowingTransit() const; - void - PutTransitHop(TransitHop* hop); + bool + HasTransitHop(const TransitHopInfo& info); - IHopHandler* - GetByUpstream(const RouterID& id, const PathID_t& path); + bool + HandleRelayCommit(const LR_CommitMessage* msg); - IHopHandler* - GetByDownstream(const RouterID& id, const PathID_t& path); + void + PutTransitHop(TransitHop* hop); - bool - ForwardLRCM(const RouterID& nextHop, std::deque< EncryptedFrame >& frames); + IHopHandler* + GetByUpstream(const RouterID& id, const PathID_t& path); - bool - HopIsUs(const PubKey& k) const; + IHopHandler* + GetByDownstream(const RouterID& id, const PathID_t& path); - bool - HandleLRUM(const RelayUpstreamMessage* msg); + bool + ForwardLRCM(const RouterID& nextHop, + std::deque< EncryptedFrame >& frames); - bool - HandleLRDM(const RelayDownstreamMessage* msg); + bool + HopIsUs(const PubKey& k) const; - void - AddOwnPath(Path* p); + bool + HandleLRUM(const RelayUpstreamMessage* msg); - typedef std::multimap< PathID_t, TransitHop* > TransitHopsMap_t; + bool + HandleLRDM(const RelayDownstreamMessage* msg); - typedef std::pair< std::mutex, TransitHopsMap_t > SyncTransitMap_t; + void + AddOwnPath(PathSet* set, Path* p); - typedef std::map< PathID_t, Path* > OwnedPathsMap_t; + typedef std::multimap< PathID_t, TransitHop* > TransitHopsMap_t; - typedef std::pair< std::mutex, OwnedPathsMap_t > SyncOwnedPathsMap_t; + typedef std::pair< std::mutex, TransitHopsMap_t > SyncTransitMap_t; - llarp_threadpool* - Worker(); + // maps path id -> pathset owner of path + typedef std::map< PathID_t, PathSet* > OwnedPathsMap_t; - llarp_crypto* - Crypto(); + typedef std::pair< std::mutex, OwnedPathsMap_t > SyncOwnedPathsMap_t; - llarp_logic* - Logic(); + llarp_threadpool* + Worker(); - llarp_router* - Router(); + llarp_crypto* + Crypto(); - byte_t* - EncryptionSecretKey(); + llarp_logic* + Logic(); - const byte_t* - OurRouterID() const; + llarp_router* + Router(); - private: - llarp_router* m_Router; - SyncTransitMap_t m_TransitPaths; - SyncTransitMap_t m_Paths; - SyncOwnedPathsMap_t m_OurPaths; + byte_t* + EncryptionSecretKey(); - bool m_AllowTransit; - }; + const byte_t* + OurRouterID() const; + + private: + llarp_router* m_Router; + SyncTransitMap_t m_TransitPaths; + SyncTransitMap_t m_Paths; + SyncOwnedPathsMap_t m_OurPaths; + std::list< llarp_pathbuilder_context* > m_PathBuilders; + bool m_AllowTransit; + }; + } // namespace path } // namespace llarp #endif diff --git a/include/llarp/pathset.hpp b/include/llarp/pathset.hpp new file mode 100644 index 000000000..894629f92 --- /dev/null +++ b/include/llarp/pathset.hpp @@ -0,0 +1,63 @@ +#ifndef LLARP_PATHSET_HPP +#define LLARP_PATHSET_HPP + +#include +#include +#include + +namespace llarp +{ + namespace path + { + enum PathStatus + { + ePathBuilding, + ePathEstablished, + ePathTimeout, + ePathExpired + }; + // forward declare + struct Path; + + /// a set of paths owned by an entity + struct PathSet + { + /// construct + /// @params numPaths the number of paths to maintain + PathSet(size_t numPaths); + + void + RemovePath(Path* path); + + void + HandlePathBuilt(Path* path); + + void + AddPath(Path* path); + + Path* + GetByUpstream(const RouterID& remote, const PathID_t& rxid); + + void + ExpirePaths(llarp_time_t now); + + size_t + NumInStatus(PathStatus st) const; + + /// return true if we should build another path + bool + ShouldBuildMore() const; + + private: + typedef std::map< PathID_t, Path* > PathMap_t; + // (tx,rx) + typedef std::tuple< PathMap_t, PathMap_t > PathContainer_t; + + size_t m_NumPaths; + PathContainer_t m_Paths; + }; + + } // namespace path +} // namespace llarp + +#endif \ No newline at end of file diff --git a/include/llarp/routing/handler.hpp b/include/llarp/routing/handler.hpp index 15a3e1f63..8124d1454 100644 --- a/include/llarp/routing/handler.hpp +++ b/include/llarp/routing/handler.hpp @@ -2,6 +2,9 @@ #define LLARP_ROUTING_HANDLER_HPP #include +#include +#include +#include namespace llarp { @@ -12,6 +15,15 @@ namespace llarp { virtual bool HandleHiddenServiceData(llarp_buffer_t buf) = 0; + + virtual bool + HandlePathConfirmMessage(const PathConfirmMessage* msg) = 0; + + virtual bool + HandlePathLatencyMessage(const PathLatencyMessage* msg) = 0; + + virtual bool + HandleDHTMessage(const llarp::dht::IMessage* msg) = 0; }; } // namespace routing } // namespace llarp diff --git a/llarp/api/create_session.cpp b/llarp/api/create_session.cpp index c1d62b79f..a7cd75c59 100644 --- a/llarp/api/create_session.cpp +++ b/llarp/api/create_session.cpp @@ -7,7 +7,6 @@ namespace llarp { namespace api { - bool CreateSessionMessage::DecodeParams(llarp_buffer_t *buf) { diff --git a/llarp/codel.hpp b/llarp/codel.hpp new file mode 100644 index 000000000..8c16d9b97 --- /dev/null +++ b/llarp/codel.hpp @@ -0,0 +1,74 @@ +#ifndef LLARP_CODEL_QUEUE_HPP +#define LLARP_CODEL_QUEUE_HPP +#include +#include +#include +#include +#include + +namespace llarp +{ + namespace util + { + template < typename T, typename GetTime, llarp_time_t dropMs = 20, + llarp_time_t initialIntervalMs = 100 > + struct CoDelQueue + { + struct CoDelCompare + { + GetTime getTime = GetTime(); + bool + operator()(const T& left, const T& right) const + { + return getTime(left) < getTime(right); + } + }; + + void + Put(T* item) + { + std::unique_lock< std::mutex > lock(m_QueueMutex); + m_Queue.push(*item); + } + + void + Process(std::queue< T >& result) + { + llarp_time_t lowest = 0xFFFFFFFFFFFFFFFFUL; + auto start = llarp_time_now_ms(); + std::unique_lock< std::mutex > lock(m_QueueMutex); + while(m_Queue.size()) + { + const auto& item = m_Queue.top(); + auto dlt = start - getTime(item); + lowest = std::min(dlt, lowest); + if(m_Queue.size() == 1) + { + if(lowest > dropMs) + { + // drop + nextTickInterval = initialIntervalMs / std::sqrt(++dropNum); + m_Queue.pop(); + return; + } + else + { + nextTickInterval = initialIntervalMs; + dropNum = 0; + } + } + result.push(item); + m_Queue.pop(); + } + } + + GetTime getTime = GetTime(); + size_t dropNum = 0; + llarp_time_t nextTickInterval = initialIntervalMs; + std::mutex m_QueueMutex; + std::priority_queue< T, std::vector< T >, CoDelCompare > m_Queue; + }; + } // namespace util +} // namespace llarp + +#endif \ No newline at end of file diff --git a/llarp/context.cpp b/llarp/context.cpp index c3b759e88..40b4323c1 100644 --- a/llarp/context.cpp +++ b/llarp/context.cpp @@ -29,7 +29,7 @@ namespace llarp bool Context::ReloadConfig() { - //llarp::Info("loading config at ", configfile); + // llarp::Info("loading config at ", configfile); if(llarp_load_config(config, configfile.c_str())) { llarp_free_config(&config); @@ -94,7 +94,7 @@ namespace llarp llarp::Error("nodedb_dir is incorrect"); return 0; } - //llarp::Info("nodedb_dir [", nodedb_dir, "] configured!"); + // llarp::Info("nodedb_dir [", nodedb_dir, "] configured!"); ssize_t loaded = llarp_nodedb_load_dir(nodedb, nodedb_dir); llarp::Info("nodedb_dir loaded ", loaded, " RCs from [", nodedb_dir, "]"); if(loaded < 0) diff --git a/llarp/crypto_async.cpp b/llarp/crypto_async.cpp index d02983ae7..a20c6fabb 100644 --- a/llarp/crypto_async.cpp +++ b/llarp/crypto_async.cpp @@ -333,30 +333,7 @@ namespace iwp hmac_then_decrypt(void *user) { iwp_async_frame *frame = static_cast< iwp_async_frame * >(user); - auto crypto = frame->iwp->crypto; - byte_t *hmac = frame->buf; - byte_t *nonce = frame->buf + 32; - byte_t *body = frame->buf + 64; - - llarp::ShortHash digest; - - llarp_buffer_t buf; - buf.base = nonce; - buf.cur = buf.base; - buf.sz = frame->sz - 32; - - // h = MDS(n + x, S) - crypto->hmac(digest, buf, frame->sessionkey); - // check hmac - frame->success = memcmp(digest, hmac, 32) == 0; - // x = SE(S, p, n[0:24]) - buf.base = body; - buf.cur = buf.base; - buf.sz = frame->sz - 64; - crypto->xchacha20(buf, frame->sessionkey, nonce); - // call result RIGHT HERE - // frame->hook(frame); - // delete frame; + iwp_decrypt_frame(frame); // inform result llarp_logic_queue_job(frame->iwp->logic, {frame, &inform_frame_done}); } @@ -365,25 +342,7 @@ namespace iwp encrypt_then_hmac(void *user) { iwp_async_frame *frame = static_cast< iwp_async_frame * >(user); - auto crypto = frame->iwp->crypto; - byte_t *hmac = frame->buf; - byte_t *nonce = frame->buf + 32; - byte_t *body = frame->buf + 64; - - llarp_buffer_t buf; - buf.base = body; - buf.cur = buf.base; - buf.sz = frame->sz - 64; - - // randomize N - crypto->randbytes(nonce, 32); - // x = SE(S, p, n[0:24]) - crypto->xchacha20(buf, frame->sessionkey, nonce); - // h = MDS(n + x, S) - buf.base = nonce; - buf.cur = buf.base; - buf.sz = frame->sz - 32; - crypto->hmac(hmac, buf, frame->sessionkey); + iwp_encrypt_frame(frame); // call result RIGHT HERE frame->hook(frame); delete frame; @@ -399,6 +358,58 @@ iwp_call_async_keygen(struct llarp_async_iwp *iwp, llarp_threadpool_queue_job(iwp->worker, {keygen, &iwp::keygen}); } +bool +iwp_decrypt_frame(struct iwp_async_frame *frame) +{ + auto crypto = frame->iwp->crypto; + byte_t *hmac = frame->buf; + byte_t *nonce = frame->buf + 32; + byte_t *body = frame->buf + 64; + + llarp::ShortHash digest; + + llarp_buffer_t buf; + buf.base = nonce; + buf.cur = buf.base; + buf.sz = frame->sz - 32; + + // h = MDS(n + x, S) + crypto->hmac(digest, buf, frame->sessionkey); + // check hmac + frame->success = memcmp(digest, hmac, 32) == 0; + // x = SE(S, p, n[0:24]) + buf.base = body; + buf.cur = buf.base; + buf.sz = frame->sz - 64; + crypto->xchacha20(buf, frame->sessionkey, nonce); + return frame->success; +} + +bool +iwp_encrypt_frame(struct iwp_async_frame *frame) +{ + auto crypto = frame->iwp->crypto; + byte_t *hmac = frame->buf; + byte_t *nonce = frame->buf + 32; + byte_t *body = frame->buf + 64; + + llarp_buffer_t buf; + buf.base = body; + buf.cur = buf.base; + buf.sz = frame->sz - 64; + + // randomize N + crypto->randbytes(nonce, 32); + // x = SE(S, p, n[0:24]) + crypto->xchacha20(buf, frame->sessionkey, nonce); + // h = MDS(n + x, S) + buf.base = nonce; + buf.cur = buf.base; + buf.sz = frame->sz - 32; + crypto->hmac(hmac, buf, frame->sessionkey); + return true; +} + void iwp_call_async_gen_intro(struct llarp_async_iwp *iwp, struct iwp_async_intro *intro) diff --git a/llarp/dht.cpp b/llarp/dht.cpp index 587a47860..d5bd009a2 100644 --- a/llarp/dht.cpp +++ b/llarp/dht.cpp @@ -81,14 +81,6 @@ namespace llarp namespace dht { - Key_t ZeroKey; - - bool - Key_t::IsZero() const - { - return memcmp(l, ZeroKey.l, 32) == 0; - } - GotRouterMessage::~GotRouterMessage() { for(auto &rc : R) diff --git a/llarp/encode.cpp b/llarp/encode.cpp index f337a1042..7e55ecf43 100644 --- a/llarp/encode.cpp +++ b/llarp/encode.cpp @@ -3,8 +3,8 @@ namespace llarp { - - int char2int(char input) + int + char2int(char input) { if(input >= '0' && input <= '9') return input - '0'; @@ -15,13 +15,13 @@ namespace llarp throw std::invalid_argument("Invalid input string"); } - void HexDecode(const char* src, uint8_t* target) + void + HexDecode(const char* src, uint8_t* target) { while(*src && src[1]) { - *(target++) = char2int(*src)*16 + char2int(src[1]); + *(target++) = char2int(*src) * 16 + char2int(src[1]); src += 2; } } - } diff --git a/llarp/iwp_link.cpp b/llarp/iwp_link.cpp index 8cb212e06..268103784 100644 --- a/llarp/iwp_link.cpp +++ b/llarp/iwp_link.cpp @@ -4,6 +4,7 @@ #include #include #include "address_info.hpp" +#include "codel.hpp" #include "link/encoder.hpp" #include @@ -657,6 +658,16 @@ namespace iwp } }; + /// get the time from a iwp_async_frame + struct FrameGetTime + { + llarp_time_t + operator()(const iwp_async_frame &frame) const + { + return frame.created; + } + }; + struct session { llarp_udp_io *udp; @@ -676,9 +687,22 @@ namespace iwp llarp_link_establish_job *establish_job = nullptr; + /// cached timestamp for frame creation + llarp_time_t now; uint32_t establish_job_id = 0; uint32_t frames = 0; bool working = false; + + llarp::util::CoDelQueue< iwp_async_frame, FrameGetTime > inboundFrames; + llarp::util::CoDelQueue< iwp_async_frame, FrameGetTime > outboundFrames; + + std::mutex m_DecryptedFramesMutex; + std::queue< iwp_async_frame > decryptedFrames; + std::mutex m_EncryptedFramesMutex; + std::queue< iwp_async_frame > encryptedFrames; + uint32_t pump_send_timer_id = 0; + uint32_t pump_recv_timer_id = 0; + llarp::Addr addr; iwp_async_intro intro; iwp_async_introack introack; @@ -770,21 +794,50 @@ namespace iwp return false; } + static void + handle_codel_inbound_pump(void *u, uint64_t orig, uint64_t left); + static void + handle_codel_outbound_pump(void *u, uint64_t orig, uint64_t left); + + void + PumpCrypto(); + + void + PumpCodelInbound() + { + pump_recv_timer_id = llarp_logic_call_later( + logic, + {inboundFrames.nextTickInterval, this, &handle_codel_inbound_pump}); + } + + void + PumpCodelOutbound() + { + pump_send_timer_id = llarp_logic_call_later( + logic, + {outboundFrames.nextTickInterval, this, &handle_codel_outbound_pump}); + } + void pump() { + // TODO: in codel the timestamp may cause excssive drop when all the + // packets have a similar timestamp + now = llarp_time_now_ms(); llarp_buffer_t buf; while(frame.next_frame(&buf)) { encrypt_frame_async_send(buf.base, buf.sz); frame.pop_next_frame(); } + PumpCrypto(); } // this is called from net thread void recv(const void *buf, size_t sz) { + now = llarp_time_now_ms(); switch(state) { case eInitial: @@ -832,9 +885,11 @@ namespace iwp crypto->shorthash(digest, buf); auto id = frame.txids++; auto msg = new transit_message(buf, digest, id); + + // enter state + EnterState(eLIMSent); // put into outbound send queue add_outbound_message(id, msg); - EnterState(eLIMSent); } else llarp::Error("LIM Encode failed"); @@ -845,43 +900,10 @@ namespace iwp // return true if we should be removed bool - Tick(uint64_t now) - { - if(timedout(now, SESSION_TIMEOUT)) - { - // we are timed out - // when we are done doing stuff with all of our frames from the crypto - // workers we are done - llarp::Debug(addr, " timed out with ", frames, " frames left"); - if(working) - return false; - return frames == 0; - } - if(is_invalidated()) - { - // both sides agreeed to session invalidation - // terminate our session when all of our frames from the crypto workers - // are done - llarp::Debug(addr, " invaldiated session with ", frames, - " frames left"); - if(working) - return false; - return frames == 0; - } - // send keepalive if we are established or a session is made - if(state == eEstablished || state == eLIMSent) - send_keepalive(this); + Tick(uint64_t now); - // pump frames - if(state == eEstablished) - { - frame.retransmit(); - pump(); - } - - // TODO: determine if we are too idle - return false; - } + static void + codel_timer_handler(void *user, uint64_t orig, uint64_t left); bool IsEstablished() @@ -1001,13 +1023,11 @@ namespace iwp { session *self = static_cast< session * >(frame->user); llarp::Debug("rx ", frame->sz, " frames=", self->frames); - self->frames--; if(frame->success) { if(self->frame.process(frame->buf + 64, frame->sz - 64)) { self->frame.alive(); - self->pump(); } else llarp::Error("invalid frame from ", self->addr); @@ -1021,14 +1041,38 @@ namespace iwp { if(sz > 64) { - iwp_async_frame *frame = alloc_frame(buf, sz); - frame->hook = &handle_frame_decrypt; - iwp_call_async_frame_decrypt(iwp, frame); + alloc_frame(inboundFrames, buf, sz); } else llarp::Warn("short packet of ", sz, " bytes"); } + static void + handle_crypto_pump(void *u); + + void + DecryptInboundFrames() + { + std::queue< iwp_async_frame > outq; + std::queue< iwp_async_frame > inq; + inboundFrames.Process(inq); + while(inq.size()) + { + auto &front = inq.front(); + if(iwp_decrypt_frame(&front)) + outq.push(front); + inq.pop(); + } + { + std::unique_lock< std::mutex > lock(m_DecryptedFramesMutex); + while(outq.size()) + { + decryptedFrames.push(outq.front()); + outq.pop(); + } + } + } + static void handle_frame_encrypt(iwp_async_frame *frame) { @@ -1037,23 +1081,26 @@ namespace iwp if(llarp_ev_udp_sendto(self->udp, self->addr, frame->buf, frame->sz) == -1) llarp::Warn("sendto failed"); - self->frames--; } + template < typename Queue > iwp_async_frame * - alloc_frame(const void *buf, size_t sz) + alloc_frame(Queue &q, const void *buf, size_t sz) { // TODO don't hard code 1500 if(sz > 1500) return nullptr; - iwp_async_frame *frame = new iwp_async_frame(); + iwp_async_frame *frame = new iwp_async_frame; if(buf) memcpy(frame->buf, buf, sz); + frame->iwp = iwp; frame->sz = sz; frame->user = this; frame->sessionkey = sessionkey; - frames++; + /// TODO: this could be rather slow + frame->created = now; + q.Put(frame); return frame; } @@ -1061,14 +1108,35 @@ namespace iwp encrypt_frame_async_send(const void *buf, size_t sz) { // 64 bytes frame overhead for nonce and hmac - iwp_async_frame *frame = alloc_frame(nullptr, sz + 64); + iwp_async_frame *frame = alloc_frame(outboundFrames, nullptr, sz + 64); memcpy(frame->buf + 64, buf, sz); auto padding = rand() % MAX_PAD; if(padding) crypto->randbytes(frame->buf + 64 + sz, padding); frame->sz += padding; - frame->hook = &handle_frame_encrypt; - iwp_call_async_frame_encrypt(iwp, frame); + } + + void + EncryptOutboundFrames() + { + std::queue< iwp_async_frame > q; + std::queue< iwp_async_frame > outq; + outboundFrames.Process(outq); + while(outq.size()) + { + auto &front = outq.front(); + if(iwp_encrypt_frame(&front)) + q.push(front); + outq.pop(); + } + { + std::unique_lock< std::mutex > lock(m_EncryptedFramesMutex); + while(q.size()) + { + encryptedFrames.push(q.front()); + q.pop(); + } + } } static void @@ -1203,6 +1271,11 @@ namespace iwp { frame.alive(); state = st; + if(state == eLIMSent || state == eSessionStartSent) + { + PumpCodelInbound(); + PumpCodelOutbound(); + } } }; @@ -1216,13 +1289,14 @@ namespace iwp llarp_crypto *crypto; llarp_ev_loop *netloop; llarp_async_iwp *iwp; + llarp_threadpool *worker; llarp_link *parent = nullptr; llarp_udp_io udp; llarp::Addr addr; char keyfile[255]; uint32_t timeout_job_id; - typedef std::unordered_map< llarp::Addr, llarp_link_session, + typedef std::unordered_map< llarp::Addr, llarp_link_session *, llarp::addrhash > LinkMap_t; @@ -1243,6 +1317,7 @@ namespace iwp router = r; crypto = c; logic = l; + worker = w; iwp = llarp_async_iwp_new(crypto, logic, w); } @@ -1277,7 +1352,7 @@ namespace iwp std::set< llarp::Addr > remove; for(auto &itr : m_sessions) { - session *s = static_cast< session * >(itr.second.impl); + session *s = static_cast< session * >(itr.second->impl); if(s && s->Tick(now)) remove.insert(itr.first); } @@ -1300,7 +1375,7 @@ namespace iwp auto inner_itr = serv->m_sessions.find(itr->second); if(inner_itr != serv->m_sessions.end()) { - llarp_link_session *link = &inner_itr->second; + llarp_link_session *link = inner_itr->second; return link->sendto(link, buf); } } @@ -1350,28 +1425,28 @@ namespace iwp if(itr == m_sessions.end()) return nullptr; else - return static_cast< session * >(itr->second.impl); + return static_cast< session * >(itr->second->impl); } void put_session(const llarp::Addr &src, session *impl) { - llarp_link_session s = {}; - s.impl = impl; - s.sendto = &session::sendto; - s.timeout = &session::is_timedout; - s.close = &session::close; - s.get_remote_router = &session::get_remote_router; - s.established = &session::set_established; - s.get_parent = &session::get_parent; + llarp_link_session *s = new llarp_link_session; + s->impl = impl; + s->sendto = &session::sendto; + s->timeout = &session::is_timedout; + s->close = &session::close; + s->get_remote_router = &session::get_remote_router; + s->established = &session::set_established; + s->get_parent = &session::get_parent; { lock_t lock(m_sessions_Mutex); - m_sessions[src] = s; - impl->parent = &m_sessions[src]; + m_sessions.emplace(src, s); + impl->parent = m_sessions[src]; + impl->frame.router = router; + impl->frame.parent = impl->parent; + impl->our_router = &router->rc; } - impl->frame.router = router; - impl->frame.parent = impl->parent; - impl->our_router = &router->rc; } void @@ -1381,8 +1456,9 @@ namespace iwp auto itr = m_sessions.begin(); while(itr != m_sessions.end()) { - session *s = static_cast< session * >(itr->second.impl); + session *s = static_cast< session * >(itr->second->impl); delete s; + delete itr->second; itr = m_sessions.erase(itr); } } @@ -1395,17 +1471,11 @@ namespace iwp { llarp::Debug("removing session ", addr); UnmapAddr(addr); - session *s = static_cast< session * >(itr->second.impl); + session *s = static_cast< session * >(itr->second->impl); s->done(); - m_sessions.erase(addr); - if(s->frames) - { - llarp::Warn("session has ", s->frames, - " left but is idle, not deallocating session so we " - "leak but don't die"); - } - else - delete s; + delete itr->second; + m_sessions.erase(itr); + delete s; } } @@ -1556,7 +1626,6 @@ namespace iwp { llarp::Error("intro verify failed from ", self->addr, " via ", self->serv->addr); - delete self; return; } self->intro_ack(); @@ -1575,11 +1644,20 @@ namespace iwp void session::done() { + auto logic = serv->logic; if(establish_job_id) { llarp_logic_remove_call(logic, establish_job_id); handle_establish_timeout(this, 0, 0); } + if(pump_recv_timer_id) + { + llarp_logic_remove_call(logic, pump_recv_timer_id); + } + if(pump_send_timer_id) + { + llarp_logic_remove_call(logic, pump_send_timer_id); + } } void @@ -1624,7 +1702,8 @@ namespace iwp frame_header hdr(tmp); hdr.flags() = self->frame.txflags; // send frame after encrypting - auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); + auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); + self->now = llarp_time_now_ms(); self->encrypt_frame_async_send(buf.base, buf.sz); } @@ -1663,7 +1742,6 @@ namespace iwp if(msg->completed()) { llarp::Debug("message transmitted msgid=", msgid); - session *impl = static_cast< session * >(parent->impl); tx.erase(msgid); delete msg; } @@ -1699,6 +1777,97 @@ namespace iwp link->session_start(); } + bool + session::Tick(llarp_time_t now) + { + if(timedout(now, SESSION_TIMEOUT)) + { + // we are timed out + // when we are done doing stuff with all of our frames from the crypto + // workers we are done + llarp::Debug(addr, " timed out with ", frames, " frames left"); + return !working; + } + if(is_invalidated()) + { + // both sides agreeed to session invalidation + // terminate our session when all of our frames from the crypto workers + // are done + llarp::Debug(addr, " invaldiated session with ", frames, " frames left"); + return !working; + } + // send keepalive if we are established or a session is made + if(state == eEstablished || state == eLIMSent) + send_keepalive(this); + + // pump frame state + if(state == eEstablished) + { + frame.retransmit(); + pump(); + } + // TODO: determine if we are too idle + return false; + } + + void + session::handle_codel_outbound_pump(void *u, uint64_t orig, uint64_t left) + { + if(left) + return; + session *self = static_cast< session * >(u); + self->pump_send_timer_id = 0; + if(self->timedout(llarp_time_now_ms())) + return; + { + std::unique_lock< std::mutex > lock(self->m_EncryptedFramesMutex); + while(self->encryptedFrames.size()) + { + auto &front = self->encryptedFrames.front(); + handle_frame_encrypt(&front); + self->encryptedFrames.pop(); + } + } + self->PumpCodelOutbound(); + self->PumpCrypto(); + } + + void + session::handle_codel_inbound_pump(void *u, uint64_t orig, uint64_t left) + { + if(left) + return; + session *self = static_cast< session * >(u); + self->pump_recv_timer_id = 0; + if(self->timedout(llarp_time_now_ms())) + return; + { + std::unique_lock< std::mutex > lock(self->m_DecryptedFramesMutex); + while(self->decryptedFrames.size()) + { + auto &front = self->decryptedFrames.front(); + handle_frame_decrypt(&front); + self->decryptedFrames.pop(); + } + } + self->PumpCodelInbound(); + self->PumpCrypto(); + } + + void + session::PumpCrypto() + { + llarp_threadpool_queue_job(serv->worker, {this, &handle_crypto_pump}); + } + + void + session::handle_crypto_pump(void *u) + { + session *self = static_cast< session * >(u); + self->EncryptOutboundFrames(); + self->DecryptInboundFrames(); + } + void session::handle_verify_session_start(iwp_async_session_start *s) { @@ -1829,7 +1998,7 @@ namespace iwp link->timeout_job_id = 0; link->logic = logic; // start cleanup timer - link->issue_cleanup_timer(2500); + link->issue_cleanup_timer(1000); return true; } @@ -1854,8 +2023,8 @@ namespace iwp iter.link = l; // TODO: race condition with cleanup timer for(auto &item : link->m_sessions) - if(item.second.impl) - if(!iter.visit(&iter, &item.second)) + if(item.second->impl) + if(!iter.visit(&iter, item.second)) return; } } @@ -1933,6 +2102,7 @@ namespace iwp delete link; return; } + link->frame.alive(); link->serv->put_session(link->addr, link); llarp::Debug("send introack to ", link->addr, " via ", link->serv->addr); if(llarp_ev_udp_sendto(link->udp, link->addr, i->buf, i->sz) == -1) diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index dd415ec2b..50fcece92 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -47,23 +47,23 @@ struct llarp_nodedb return entries.find(pk) != entries.end(); } -/* - bool - Has(const byte_t *pk) - { - llarp::PubKey test(pk); - auto itr = this->entries.begin(); - while(itr != this->entries.end()) + /* + bool + Has(const byte_t *pk) { - llarp::Info("Has byte_t [", test.size(), "] vs [", itr->first.size(), "]"); - if (memcmp(test.data(), itr->first.data(), 32) == 0) { - llarp::Info("Match"); + llarp::PubKey test(pk); + auto itr = this->entries.begin(); + while(itr != this->entries.end()) + { + llarp::Info("Has byte_t [", test.size(), "] vs [", itr->first.size(), + "]"); if (memcmp(test.data(), itr->first.data(), 32) == 0) { + llarp::Info("Match"); + } + itr++; } - itr++; + return entries.find(pk) != entries.end(); } - return entries.find(pk) != entries.end(); - } -*/ + */ bool pubKeyExists(llarp_rc *rc) @@ -185,7 +185,7 @@ struct llarp_nodedb auto itr = i.begin(); while(itr != itr.end()) { - if (fs::is_regular_file(itr->symlink_status()) && loadfile(*itr)) + if(fs::is_regular_file(itr->symlink_status()) && loadfile(*itr)) sz++; ++itr; @@ -198,12 +198,13 @@ struct llarp_nodedb { #if __APPLE__ && __MACH__ // skip .DS_Store files - if (strstr(fpath.c_str(), ".DS_Store") != 0) { + if(strstr(fpath.c_str(), ".DS_Store") != 0) + { return false; } #endif llarp_rc *rc = llarp_rc_read(fpath.c_str()); - if (!rc) + if(!rc) { llarp::Error("Signature read failed", fpath); return false; @@ -218,8 +219,10 @@ struct llarp_nodedb return true; } - bool iterate(struct llarp_nodedb_iter i) { - i.index = 0; + bool + iterate(struct llarp_nodedb_iter i) + { + i.index = 0; auto itr = entries.begin(); while(itr != entries.end()) { @@ -372,12 +375,14 @@ llarp_nodedb_load_dir(struct llarp_nodedb *n, const char *dir) } bool -llarp_nodedb_put_rc(struct llarp_nodedb *n, struct llarp_rc *rc) { +llarp_nodedb_put_rc(struct llarp_nodedb *n, struct llarp_rc *rc) +{ return n->setRC(rc); } int -llarp_nodedb_iterate_all(struct llarp_nodedb *n, struct llarp_nodedb_iter i) { +llarp_nodedb_iterate_all(struct llarp_nodedb *n, struct llarp_nodedb_iter i) +{ n->iterate(i); return n->entries.size(); } @@ -401,7 +406,7 @@ llarp_nodedb_async_load_rc(struct llarp_async_load_rc *job) struct llarp_rc * llarp_nodedb_get_rc(struct llarp_nodedb *n, const byte_t *pk) { - //llarp::Info("llarp_nodedb_get_rc [", pk, "]"); + // llarp::Info("llarp_nodedb_get_rc [", pk, "]"); if(n->Has(pk)) return n->getRC(pk); else diff --git a/llarp/path.cpp b/llarp/path.cpp index aa6e7199f..4e1ce967d 100644 --- a/llarp/path.cpp +++ b/llarp/path.cpp @@ -2,312 +2,403 @@ #include #include #include "buffer.hpp" +#include "pathbuilder.hpp" #include "router.hpp" namespace llarp { - PathContext::PathContext(llarp_router* router) - : m_Router(router), m_AllowTransit(false) + namespace path { - } + PathContext::PathContext(llarp_router* router) + : m_Router(router), m_AllowTransit(false) + { + } - PathContext::~PathContext() - { - } + PathContext::~PathContext() + { + } - void - PathContext::AllowTransit() - { - m_AllowTransit = true; - } + void + PathContext::AllowTransit() + { + m_AllowTransit = true; + } - bool - PathContext::AllowingTransit() const - { - return m_AllowTransit; - } + bool + PathContext::AllowingTransit() const + { + return m_AllowTransit; + } - llarp_threadpool* - PathContext::Worker() - { - return m_Router->tp; - } + llarp_threadpool* + PathContext::Worker() + { + return m_Router->tp; + } - llarp_crypto* - PathContext::Crypto() - { - return &m_Router->crypto; - } + llarp_crypto* + PathContext::Crypto() + { + return &m_Router->crypto; + } - llarp_logic* - PathContext::Logic() - { - return m_Router->logic; - } + llarp_logic* + PathContext::Logic() + { + return m_Router->logic; + } - byte_t* - PathContext::EncryptionSecretKey() - { - return m_Router->encryption; - } + byte_t* + PathContext::EncryptionSecretKey() + { + return m_Router->encryption; + } - bool - PathContext::HopIsUs(const PubKey& k) const - { - return memcmp(k, m_Router->pubkey(), PUBKEYSIZE) == 0; - } + bool + PathContext::HopIsUs(const PubKey& k) const + { + return memcmp(k, m_Router->pubkey(), PUBKEYSIZE) == 0; + } - bool - PathContext::ForwardLRCM(const RouterID& nextHop, - std::deque< EncryptedFrame >& frames) - { - llarp::Info("fowarding LRCM to ", nextHop); - LR_CommitMessage* msg = new LR_CommitMessage; - while(frames.size()) - { - msg->frames.push_back(frames.front()); - frames.pop_front(); - } - 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 range = map.second.equal_range(k); - for(auto i = range.first; i != range.second; ++i) + bool + PathContext::ForwardLRCM(const RouterID& nextHop, + std::deque< EncryptedFrame >& frames) + { + llarp::Info("fowarding LRCM to ", nextHop); + LR_CommitMessage* msg = new LR_CommitMessage; + while(frames.size()) + { + msg->frames.push_back(frames.front()); + frames.pop_front(); + } + return m_Router->SendToOrQueue(nextHop, msg); + } + template < typename Map_t, typename Key_t, typename CheckValue_t, + typename GetFunc_t > + IHopHandler* + MapGet(Map_t& map, const Key_t& k, CheckValue_t check, GetFunc_t get) { - if(check(i->second)) - return i->second; + std::unique_lock< std::mutex > lock(map.first); + auto range = map.second.equal_range(k); + for(auto i = range.first; i != range.second; ++i) + { + if(check(i->second)) + return get(i->second); + } + return nullptr; } - return nullptr; - } - template < typename Map_t, typename Key_t, typename CheckValue_t > - bool - MapHas(Map_t& map, const Key_t& k, CheckValue_t check) - { - std::unique_lock< std::mutex > lock(map.first); - auto range = map.second.equal_range(k); - for(auto i = range.first; i != range.second; ++i) + template < typename Map_t, typename Key_t, typename CheckValue_t > + bool + MapHas(Map_t& map, const Key_t& k, CheckValue_t check) { - if(check(i->second)) - return true; + std::unique_lock< std::mutex > lock(map.first); + auto range = map.second.equal_range(k); + for(auto i = range.first; i != range.second; ++i) + { + if(check(i->second)) + return true; + } + return false; } - return false; - } - template < typename Map_t, typename Key_t, typename Value_t > - void - MapPut(Map_t& map, const Key_t& k, const Value_t& v) - { - std::unique_lock< std::mutex > lock(map.first); - map.second.emplace(k, v); - } + template < typename Map_t, typename Key_t, typename Value_t > + void + MapPut(Map_t& map, const Key_t& k, const Value_t& v) + { + std::unique_lock< std::mutex > lock(map.first); + 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 range = map.second.equal_range(k); - for(auto i = range.first; i != range.second;) + template < typename Map_t, typename Visit_t > + void + MapIter(Map_t& map, Visit_t v) { - if(check(i->second)) - i = map.second.erase(i); - else - ++i; + std::unique_lock< std::mutex > lock(map.first); + for(const auto& item : map.second) + v(item); } - } - void - PathContext::AddOwnPath(Path* path) - { - MapPut(m_OurPaths, path->TXID(), path); - MapPut(m_OurPaths, path->RXID(), path); - } + 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 range = map.second.equal_range(k); + for(auto i = range.first; i != range.second;) + { + if(check(i->second)) + i = map.second.erase(i); + else + ++i; + } + } - bool - PathContext::HasTransitHop(const TransitHopInfo& info) - { - return MapHas(m_TransitPaths, info.txID, [info](TransitHop* hop) -> bool { - return info == hop->info; - }); - } + void + PathContext::AddOwnPath(PathSet* set, Path* path) + { + set->AddPath(path); + MapPut(m_OurPaths, path->TXID(), set); + MapPut(m_OurPaths, path->RXID(), set); + } - 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; - }); - } - - 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; - }); - } + bool + PathContext::HasTransitHop(const TransitHopInfo& info) + { + return MapHas(m_TransitPaths, info.txID, [info](TransitHop* hop) -> bool { + return info == hop->info; + }); + } - const byte_t* - PathContext::OurRouterID() const - { - return m_Router->pubkey(); - } + IHopHandler* + PathContext::GetByUpstream(const RouterID& remote, const PathID_t& id) + { + auto own = MapGet(m_OurPaths, id, + [](const PathSet* s) -> bool { + // TODO: is this right? + return true; + }, + [remote, id](PathSet* p) -> IHopHandler* { + return p->GetByUpstream(remote, id); + }); + if(own) + return own; + + return MapGet(m_TransitPaths, id, + [remote](const TransitHop* hop) -> bool { + return hop->info.upstream == remote; + }, + [](TransitHop* h) -> IHopHandler* { return h; }); + } - llarp_router* - PathContext::Router() - { - return m_Router; - } + 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; + }, + [](TransitHop* h) -> IHopHandler* { return h; }); + } - void - PathContext::PutTransitHop(TransitHop* hop) - { - MapPut(m_TransitPaths, hop->info.txID, hop); - MapPut(m_TransitPaths, hop->info.rxID, hop); - } + const byte_t* + PathContext::OurRouterID() const + { + return m_Router->pubkey(); + } - void - PathContext::ExpirePaths() - { - std::unique_lock< std::mutex > lock(m_TransitPaths.first); - 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)) + llarp_router* + PathContext::Router() + { + return m_Router; + } + + void + PathContext::PutTransitHop(TransitHop* hop) + { + MapPut(m_TransitPaths, hop->info.txID, hop); + MapPut(m_TransitPaths, hop->info.rxID, hop); + } + + void + PathContext::ExpirePaths() + { + std::unique_lock< std::mutex > lock(m_TransitPaths.first); + 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)) + { + 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; + } + for(auto& builder : m_PathBuilders) { - TransitHop* path = itr->second; - llarp::Info("transit path expired ", path); - removePaths.insert(path); + builder->ExpirePaths(now); } - ++itr; } - for(auto& p : removePaths) + + void + PathContext::BuildPaths() { - map.erase(p->info.txID); - map.erase(p->info.rxID); - delete p; + for(auto& builder : m_PathBuilders) + { + if(builder->ShouldBuildMore()) + { + builder->BuildOne(); + } + } } - } - Path::Path(llarp_path_hops* h) : hops(h->numHops) - { - for(size_t idx = 0; idx < h->numHops; ++idx) + void + PathContext::AddPathBuilder(llarp_pathbuilder_context* ctx) { - llarp_rc_copy(&hops[idx].router, &h->hops[idx].router); - hops[idx].txID.Randomize(); - hops[idx].rxID.Randomize(); + m_PathBuilders.push_back(ctx); } - for(size_t idx = (h->numHops - 1); idx > 0; --idx) + + PathHopConfig::PathHopConfig() { - hops[idx].txID = hops[idx - 1].rxID; + llarp_rc_clear(&router); } - } - const PathID_t& - Path::TXID() const - { - return hops[0].txID; - } + PathHopConfig::~PathHopConfig() + { + llarp_rc_free(&router); + } - const PathID_t& - Path::RXID() const - { - return hops[0].rxID; - } + 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); + 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; + } + } - RouterID - Path::Upstream() const - { - return hops[0].router.pubkey; - } + void + Path::SetBuildResultHook(BuildResultHookFunc func) + { + m_BuiltHook = func; + } - bool - Path::HandleUpstream(llarp_buffer_t buf, const TunnelNonce& Y, - llarp_router* r) - { - for(const auto& hop : hops) + const PathID_t& + Path::TXID() const { - r->crypto.xchacha20(buf, hop.shared, Y); + return hops[0].txID; } - RelayUpstreamMessage* msg = new RelayUpstreamMessage; - msg->X = buf; - msg->Y = Y; - msg->pathid = TXID(); - return r->SendToOrQueue(Upstream(), msg); - } - bool - Path::Expired(llarp_time_t now) const - { - return now - buildStarted > hops[0].lifetime; - } + const PathID_t& + Path::RXID() const + { + return hops[0].rxID; + } - bool - Path::HandleDownstream(llarp_buffer_t buf, const TunnelNonce& Y, + RouterID + Path::Upstream() const + { + return hops[0].router.pubkey; + } + + bool + Path::HandleUpstream(llarp_buffer_t buf, const TunnelNonce& Y, llarp_router* r) - { - for(const auto& hop : hops) { - r->crypto.xchacha20(buf, hop.shared, Y); + for(const auto& hop : hops) + { + r->crypto.xchacha20(buf, hop.shared, Y); + } + RelayUpstreamMessage* msg = new RelayUpstreamMessage; + msg->X = buf; + msg->Y = Y; + msg->pathid = TXID(); + return r->SendToOrQueue(Upstream(), msg); } - return HandleRoutingMessage(buf, r); - } - bool - Path::HandleHiddenServiceData(llarp_buffer_t buf) - { - // TODO: implement me - return false; - } + bool + Path::Expired(llarp_time_t now) const + { + if(status == ePathEstablished) + return now - buildStarted > hops[0].lifetime; + else if(status == ePathBuilding) + return now - buildStarted > PATH_BUILD_TIMEOUT; + else + return true; + } - bool - Path::HandleRoutingMessage(llarp_buffer_t buf, llarp_router* r) - { - if(!m_InboundMessageParser.ParseMessageBuffer(buf, this)) + bool + Path::HandleDownstream(llarp_buffer_t buf, const TunnelNonce& Y, + llarp_router* r) { - llarp::Warn("Failed to parse inbound routing message"); + for(const auto& hop : hops) + { + r->crypto.xchacha20(buf, hop.shared, Y); + } + return HandleRoutingMessage(buf, r); + } + + bool + Path::HandleHiddenServiceData(llarp_buffer_t buf) + { + // TODO: implement me return false; } - return true; - } - bool - Path::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)) + bool + Path::HandleRoutingMessage(llarp_buffer_t buf, llarp_router* r) + { + if(!m_InboundMessageParser.ParseMessageBuffer(buf, this)) + { + llarp::Warn("Failed to parse inbound routing message"); + return false; + } + return true; + } + + bool + Path::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)) + return false; + // rewind + buf.sz = buf.cur - buf.base; + buf.cur = buf.base; + // make nonce + TunnelNonce N; + N.Randomize(); + return HandleUpstream(buf, N, r); + } + + bool + Path::HandlePathConfirmMessage( + const llarp::routing::PathConfirmMessage* msg) + { + if(status == ePathBuilding) + { + // confirm that we build the path + status = ePathEstablished; + if(m_BuiltHook) + m_BuiltHook(this); + m_BuiltHook = nullptr; + return true; + } + llarp::Warn("got unwarrented path confirm message on rx=", RXID(), + " tx=", TXID()); return false; - // rewind - buf.sz = buf.cur - buf.base; - buf.cur = buf.base; - // make nonce - TunnelNonce N; - N.Randomize(); - return HandleUpstream(buf, N, r); - } + } + + bool + Path::HandlePathLatencyMessage( + const llarp::routing::PathLatencyMessage* msg) + { + // TODO: implement me + return false; + } + bool + Path::HandleDHTMessage(const llarp::dht::IMessage* msg) + { + // TODO: implement me + return false; + } + } // namespace path } // namespace llarp diff --git a/llarp/pathbuilder.cpp b/llarp/pathbuilder.cpp index 48595d483..803c697fe 100644 --- a/llarp/pathbuilder.cpp +++ b/llarp/pathbuilder.cpp @@ -9,7 +9,10 @@ namespace llarp template < typename User > struct AsyncPathKeyExchangeContext { - Path* path = nullptr; + typedef llarp::path::Path Path_t; + typedef llarp::path::PathSet PathSet_t; + PathSet_t* pathset = nullptr; + Path_t* path = nullptr; typedef void (*Handler)(AsyncPathKeyExchangeContext< User >*); User* user = nullptr; Handler result = nullptr; @@ -105,8 +108,8 @@ namespace llarp /// Generate all keys asynchronously and call hadler when done void - AsyncGenerateKeys(Path* p, llarp_logic* l, llarp_threadpool* pool, User* u, - Handler func) + AsyncGenerateKeys(Path_t* p, llarp_logic* l, llarp_threadpool* pool, + User* u, Handler func) { path = p; logic = l; @@ -124,16 +127,6 @@ namespace llarp } }; - PathHopConfig::PathHopConfig() - { - llarp_rc_clear(&router); - } - - PathHopConfig::~PathHopConfig() - { - llarp_rc_free(&router); - } - void pathbuilder_generated_keys( AsyncPathKeyExchangeContext< llarp_pathbuild_job >* ctx) @@ -146,8 +139,8 @@ namespace llarp llarp::Error("failed to send LRCM"); return; } - ctx->path->status = ePathBuilding; - router->paths.AddOwnPath(ctx->path); + ctx->path->status = llarp::path::ePathBuilding; + router->paths.AddOwnPath(ctx->pathset, ctx->path); ctx->user->pathBuildStarted(ctx->user); } @@ -171,16 +164,33 @@ namespace llarp AsyncPathKeyExchangeContext< llarp_pathbuild_job >* ctx = new AsyncPathKeyExchangeContext< llarp_pathbuild_job >( &job->router->crypto); - - ctx->AsyncGenerateKeys(new Path(&job->hops), job->router->logic, - job->router->tp, job, &pathbuilder_generated_keys); + ctx->pathset = job->context; + auto path = new llarp::path::Path(&job->hops); + path->SetBuildResultHook(std::bind(&llarp::path::PathSet::HandlePathBuilt, + ctx->pathset, std::placeholders::_1)); + ctx->AsyncGenerateKeys(path, job->router->logic, job->router->tp, job, + &pathbuilder_generated_keys); } } // namespace llarp llarp_pathbuilder_context::llarp_pathbuilder_context( llarp_router* p_router, struct llarp_dht_context* p_dht) - : router(p_router), dht(p_dht) + // TODO: hardcoded value + : llarp::path::PathSet(4), router(p_router), dht(p_dht) +{ + p_router->paths.AddPathBuilder(this); +} + +void +llarp_pathbuilder_context::BuildOne() { + llarp_pathbuild_job* job = new llarp_pathbuild_job; + job->context = this; + job->selectHop = nullptr; + job->hops.numHops = 4; + job->user = nullptr; + job->pathBuildStarted = [](llarp_pathbuild_job* j) { delete j; }; + llarp_pathbuilder_build_path(job); } extern "C" { @@ -200,7 +210,7 @@ llarp_pathbuilder_context_free(struct llarp_pathbuilder_context* ctx) void llarp_pathbuilder_build_path(struct llarp_pathbuild_job* job) { - if (!job->context) + if(!job->context) { llarp::Error("failed to build path because no context is set in job"); return; @@ -211,4 +221,4 @@ llarp_pathbuilder_build_path(struct llarp_pathbuild_job* job) llarp_logic_queue_job(job->router->logic, {job, &llarp::pathbuilder_start_build}); } -} // end extern c +} // end extern c diff --git a/llarp/pathbuilder.hpp b/llarp/pathbuilder.hpp index fa01cd1c2..1777a3907 100644 --- a/llarp/pathbuilder.hpp +++ b/llarp/pathbuilder.hpp @@ -2,13 +2,16 @@ #define LLARP_PATHFINDER_HPP_ #include -struct llarp_pathbuilder_context +struct llarp_pathbuilder_context : public llarp::path::PathSet { struct llarp_router* router; struct llarp_dht_context* dht; - /// copy cstr + /// construct llarp_pathbuilder_context(llarp_router* p_router, struct llarp_dht_context* p_dht); + + void + BuildOne(); }; #endif diff --git a/llarp/pathset.cpp b/llarp/pathset.cpp new file mode 100644 index 000000000..87fd091ab --- /dev/null +++ b/llarp/pathset.cpp @@ -0,0 +1,97 @@ +#include +#include + +namespace llarp +{ + namespace path + { + PathSet::PathSet(size_t num) : m_NumPaths(num) + { + } + + bool + PathSet::ShouldBuildMore() const + { + return std::get< 0 >(m_Paths).size() < m_NumPaths; + } + + void + PathSet::ExpirePaths(llarp_time_t now) + { + { + auto& map = std::get< 0 >(m_Paths); + auto itr = map.begin(); + while(itr != map.end()) + { + if(itr->second->Expired(now)) + { + itr = map.erase(itr); + } + } + } + { + auto& map = std::get< 1 >(m_Paths); + auto itr = map.begin(); + while(itr != map.end()) + { + if(itr->second->Expired(now)) + { + // delete path on second iteration + delete itr->second; + itr = map.erase(itr); + } + } + } + } + + size_t + PathSet::NumInStatus(PathStatus st) const + { + size_t count = 0; + auto& map = std::get< 0 >(m_Paths); + auto itr = map.begin(); + while(itr != map.end()) + { + if(itr->second->status == st) + ++count; + ++itr; + } + return count; + } + + void + PathSet::AddPath(Path* path) + { + std::get< 0 >(m_Paths).emplace(path->TXID(), path); + std::get< 1 >(m_Paths).emplace(path->RXID(), path); + } + + void + PathSet::RemovePath(Path* path) + { + std::get< 0 >(m_Paths).erase(path->TXID()); + std::get< 1 >(m_Paths).erase(path->RXID()); + } + + Path* + PathSet::GetByUpstream(const RouterID& remote, const PathID_t& rxid) + { + auto& set = std::get< 1 >(m_Paths); + auto itr = set.begin(); + while(itr != set.end()) + { + if(itr->second->Upstream() == remote) + return itr->second; + ++itr; + } + return nullptr; + } + + void + PathSet::HandlePathBuilt(Path* path) + { + // TODO: implement me + } + + } // namespace path +} // namespace llarp \ No newline at end of file diff --git a/llarp/relay_commit.cpp b/llarp/relay_commit.cpp index bbe0469dd..3bbd78e15 100644 --- a/llarp/relay_commit.cpp +++ b/llarp/relay_commit.cpp @@ -155,18 +155,20 @@ namespace llarp struct LRCMFrameDecrypt { + typedef llarp::path::PathContext Context; + typedef llarp::path::TransitHop Hop; typedef AsyncFrameDecrypter< LRCMFrameDecrypt > Decrypter; Decrypter* decrypter; std::deque< EncryptedFrame > frames; - PathContext* context; + Context* context; // decrypted record LR_CommitRecord record; // the actual hop - TransitHop* hop; + Hop* hop; - LRCMFrameDecrypt(PathContext* ctx, Decrypter* dec, + LRCMFrameDecrypt(Context* ctx, Decrypter* dec, const LR_CommitMessage* commit) - : decrypter(dec), context(ctx), hop(new TransitHop) + : decrypter(dec), context(ctx), hop(new Hop) { for(const auto& f : commit->frames) frames.push_back(f); @@ -276,7 +278,7 @@ namespace llarp }; bool - LR_CommitMessage::AsyncDecrypt(PathContext* context) const + LR_CommitMessage::AsyncDecrypt(llarp::path::PathContext* context) const { LRCMFrameDecrypt::Decrypter* decrypter = new LRCMFrameDecrypt::Decrypter( context->Crypto(), context->EncryptionSecretKey(), diff --git a/llarp/router.cpp b/llarp/router.cpp index 3bc5604ea..2b577f14d 100644 --- a/llarp/router.cpp +++ b/llarp/router.cpp @@ -356,6 +356,7 @@ llarp_router::HandleExploritoryPathBuildStarted(llarp_pathbuild_job *job) delete job; } +// TODO: do we still need this? void llarp_router::BuildExploritoryPath() { @@ -379,7 +380,7 @@ llarp_router::Tick() auto N = llarp_nodedb_num_loaded(nodedb); if(N > 5) { - BuildExploritoryPath(); + paths.BuildPaths(); } else { @@ -595,16 +596,14 @@ llarp_router::Run() // set public encryption key llarp_rc_set_pubenckey(&rc, llarp::seckey_topublic(encryption)); - char ftmp[68] = {0}; - const char *hexKey = llarp::HexEncode< llarp::PubKey, - decltype(ftmp) >(llarp::seckey_topublic(encryption), - ftmp); + char ftmp[68] = {0}; + const char *hexKey = llarp::HexEncode< llarp::PubKey, decltype(ftmp) >( + llarp::seckey_topublic(encryption), ftmp); llarp::Info("Your Encryption pubkey ", hexKey); // set public signing key llarp_rc_set_pubsigkey(&rc, llarp::seckey_topublic(identity)); - hexKey = llarp::HexEncode< llarp::PubKey, - decltype(ftmp) >(llarp::seckey_topublic(identity), - ftmp); + hexKey = llarp::HexEncode< llarp::PubKey, decltype(ftmp) >( + llarp::seckey_topublic(identity), ftmp); llarp::Info("Your Identity pubkey ", hexKey); llarp_rc_sign(&crypto, identity, &rc); @@ -641,14 +640,16 @@ llarp_router::Run() // immediate connect all for service node uint64_t delay = rand() % 100; llarp_logic_call_later(logic, {delay, this, &ConnectAll}); - //llarp_logic_call_later(logic, {static_cast(delay), this, &ConnectAll}); + // llarp_logic_call_later(logic, {static_cast(delay), this, + // &ConnectAll}); } else { // delayed connect all for clients uint64_t delay = ((rand() % 10) * 500) + 1000; llarp_logic_call_later(logic, {delay, this, &ConnectAll}); - //llarp_logic_call_later(logic, {static_cast(delay), this, &ConnectAll}); + // llarp_logic_call_later(logic, {static_cast(delay), this, + // &ConnectAll}); } llarp::PubKey ourPubkey = pubkey(); @@ -850,7 +851,7 @@ llarp_rc_read(const char *fpath) return 0; f.read((char *)buf.base, sz); - //printf("contents[%s]\n", tmpc); + // printf("contents[%s]\n", tmpc); llarp_rc *rc = new llarp_rc; llarp::Zero(rc, sizeof(llarp_rc)); if(!llarp_rc_bdecode(rc, &buf)) @@ -977,12 +978,12 @@ llarp_findOrCreateIdentity(llarp_crypto *crypto, const char *fpath, return false; } -} // end extern C +} // end extern C // C++ ... bool llarp_findOrCreateEncryption(llarp_crypto *crypto, const char *fpath, - llarp::SecretKey *encryption) + llarp::SecretKey *encryption) { llarp::Debug("find or create ", fpath); fs::path path(fpath); diff --git a/llarp/router.hpp b/llarp/router.hpp index 897248550..d6229ce2f 100644 --- a/llarp/router.hpp +++ b/llarp/router.hpp @@ -58,7 +58,7 @@ struct llarp_router llarp_threadpool *tp; llarp_logic *logic; llarp_crypto crypto; - llarp::PathContext paths; + llarp::path::PathContext paths; llarp::SecretKey identity; llarp::SecretKey encryption; llarp_threadpool *disk; diff --git a/llarp/routing/path_confirm.cpp b/llarp/routing/path_confirm.cpp index c2263d8d4..18d86f6e8 100644 --- a/llarp/routing/path_confirm.cpp +++ b/llarp/routing/path_confirm.cpp @@ -44,9 +44,7 @@ namespace llarp bool PathConfirmMessage::HandleMessage(IMessageHandler* h) const { - llarp::Info("got path confirm created=", pathCreated, - " lifetime=", pathLifetime); - return true; + return h && h->HandlePathConfirmMessage(this); } } // namespace routing diff --git a/llarp/transit_hop.cpp b/llarp/transit_hop.cpp index e0d324cb7..dcb3ec2a5 100644 --- a/llarp/transit_hop.cpp +++ b/llarp/transit_hop.cpp @@ -4,85 +4,87 @@ namespace llarp { - bool - TransitHop::Expired(llarp_time_t now) const + namespace path { - return now - started > lifetime; - } - - TransitHopInfo::TransitHopInfo(const TransitHopInfo& other) - : txID(other.txID) - , rxID(other.rxID) - , upstream(other.upstream) - , downstream(other.downstream) - { - } + bool + TransitHop::Expired(llarp_time_t now) const + { + return now - started > lifetime; + } - TransitHopInfo::TransitHopInfo(const RouterID& down, - const LR_CommitRecord& record) - : txID(record.txid) - , rxID(record.rxid) - , upstream(record.nextHop) - , downstream(down) - { - } + TransitHopInfo::TransitHopInfo(const TransitHopInfo& other) + : txID(other.txID) + , rxID(other.rxID) + , upstream(other.upstream) + , downstream(other.downstream) + { + } - TransitHop::TransitHop(const TransitHop& other) - : info(other.info) - , pathKey(other.pathKey) - , started(other.started) - , lifetime(other.lifetime) - , version(other.version) - { - } + TransitHopInfo::TransitHopInfo(const RouterID& down, + const LR_CommitRecord& record) + : txID(record.txid) + , rxID(record.rxid) + , upstream(record.nextHop) + , downstream(down) + { + } - 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)) + TransitHop::TransitHop(const TransitHop& other) + : info(other.info) + , pathKey(other.pathKey) + , started(other.started) + , lifetime(other.lifetime) + , version(other.version) { - 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.txID; - msg->Y = Y; + 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); + } - 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::HandleDownstream(llarp_buffer_t buf, const TunnelNonce& Y, + llarp_router* r) + { + RelayDownstreamMessage* msg = new RelayDownstreamMessage; + msg->pathid = info.txID; + msg->Y = Y; - bool - TransitHop::HandleUpstream(llarp_buffer_t buf, const TunnelNonce& Y, - llarp_router* r) - { - RelayUpstreamMessage* msg = new RelayUpstreamMessage; - 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); + } - 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); - } + bool + TransitHop::HandleUpstream(llarp_buffer_t buf, const TunnelNonce& Y, + llarp_router* r) + { + RelayUpstreamMessage* msg = new RelayUpstreamMessage; + msg->pathid = info.rxID; + 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 path } // namespace llarp