From e20ae56cabc02b63e4af9ea6d825b6d0b6188179 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20B=C3=A9raud?= Date: Thu, 12 Oct 2017 01:02:24 +0200 Subject: [PATCH] dht: support client mode In client mode, a node won't store data and won't participate in routing. --- include/opendht/node.h | 4 +++- include/opendht/node_cache.h | 5 +++-- src/network_engine.cpp | 12 +++++++----- src/node.cpp | 5 ++--- src/node_cache.cpp | 16 ++++++++-------- src/parsed_message.h | 5 +++++ 6 files changed, 28 insertions(+), 19 deletions(-) diff --git a/include/opendht/node.h b/include/opendht/node.h index fa00d4dd..0332a3a5 100644 --- a/include/opendht/node.h +++ b/include/opendht/node.h @@ -40,11 +40,12 @@ using SocketCb = std::function&, RequestAnswer&&)>; struct Node { InfoHash id; SockAddr addr; + bool is_client {false}; time_point time {time_point::min()}; /* last time eared about */ time_point reply_time {time_point::min()}; /* time of last correct reply received */ - Node(const InfoHash& id, const SockAddr& addr); + Node(const InfoHash& id, const SockAddr& addr, bool client=false); Node(const InfoHash& id, const sockaddr* sa, socklen_t salen) : Node(id, SockAddr(sa, salen)) {} @@ -57,6 +58,7 @@ struct Node { std::string getAddrStr() const { return addr.toString(); } + bool isClient() const { return is_client; } /** * Makes notice about an additionnal authentication error with this node. Up diff --git a/include/opendht/node_cache.h b/include/opendht/node_cache.h index d18b7664..e5f90868 100644 --- a/include/opendht/node_cache.h +++ b/include/opendht/node_cache.h @@ -27,7 +27,7 @@ namespace dht { struct NodeCache { std::shared_ptr getNode(const InfoHash& id, sa_family_t family); - std::shared_ptr getNode(const InfoHash& id, const SockAddr&, time_point now, bool confirmed); + std::shared_ptr getNode(const InfoHash& id, const SockAddr&, time_point now, bool confirmed, bool client=false); std::vector> getCachedNodes(const InfoHash& id, sa_family_t sa_f, size_t count); /** @@ -41,10 +41,11 @@ private: class NodeMap : public std::map> { public: std::shared_ptr getNode(const InfoHash& id); - std::shared_ptr getNode(const InfoHash& id, const SockAddr&, time_point now, bool confirmed); + std::shared_ptr getNode(const InfoHash& id, const SockAddr&, time_point now, bool confirmed, bool client); void clearBadNodes(); }; + NodeMap& cache(sa_family_t af) { return af == AF_INET ? cache_4 : cache_6; } NodeMap cache_4; NodeMap cache_6; }; diff --git a/src/network_engine.cpp b/src/network_engine.cpp index 2b02c427..4c25e726 100644 --- a/src/network_engine.cpp +++ b/src/network_engine.cpp @@ -399,9 +399,9 @@ void NetworkEngine::process(std::unique_ptr&& msg, const SockAddr& from) { const auto& now = scheduler.time(); + auto node = cache.getNode(msg->id, from, now, true, msg->is_client); if (msg->type == MessageType::Error or msg->type == MessageType::Reply) { - auto node = cache.getNode(msg->id, from, now, true); auto rsocket = node->getSocket(msg->tid); auto req = node->getRequest(msg->tid); @@ -414,14 +414,16 @@ NetworkEngine::process(std::unique_ptr&& msg, const SockAddr& fro requests.erase(req_it); } else { node->received(now, req); - onNewNode(node, 1); + if (not node->is_client) + onNewNode(node, 1); throw DhtProtocolException {DhtProtocolException::UNKNOWN_TID, "Can't find transaction", msg->id}; } } node->received(now, req); - onNewNode(node, 2); + if (not node->is_client) + onNewNode(node, 2); onReportedAddr(msg->id, msg->addr); if (req and (req->cancelled() or req->expired() or req->completed())) { @@ -463,9 +465,9 @@ NetworkEngine::process(std::unique_ptr&& msg, const SockAddr& fro break; } } else { - auto node = cache.getNode(msg->id, from, now, true); node->received(now, {}); - onNewNode(node, 1); + if (not node->is_client) + onNewNode(node, 1); try { switch (msg->type) { case MessageType::Ping: diff --git a/src/node.cpp b/src/node.cpp index 6bb25d66..26cdb8de 100644 --- a/src/node.cpp +++ b/src/node.cpp @@ -31,9 +31,8 @@ constexpr std::chrono::minutes Node::NODE_GOOD_TIME; constexpr std::chrono::seconds Node::MAX_RESPONSE_TIME; -Node::Node(const InfoHash& id, const SockAddr& addr) -: id(id), - addr(addr) +Node::Node(const InfoHash& id, const SockAddr& addr, bool client) +: id(id), addr(addr), is_client(client) { crypto::random_device rd; transaction_id = TransactionDist{1}(rd); diff --git a/src/node_cache.cpp b/src/node_cache.cpp index 4bc51215..f3a92334 100644 --- a/src/node_cache.cpp +++ b/src/node_cache.cpp @@ -22,19 +22,19 @@ namespace dht { std::shared_ptr NodeCache::getNode(const InfoHash& id, sa_family_t family) { - return (family == AF_INET ? cache_4 : cache_6).getNode(id); + return cache(family).getNode(id); } std::shared_ptr -NodeCache::getNode(const InfoHash& id, const SockAddr& addr, time_point now, bool confirm) { +NodeCache::getNode(const InfoHash& id, const SockAddr& addr, time_point now, bool confirm, bool client) { if (id == zeroes) return std::make_shared(id, addr); - return (addr.getFamily() == AF_INET ? cache_4 : cache_6).getNode(id, addr, now, confirm); + return cache(addr.getFamily()).getNode(id, addr, now, confirm, client); } std::vector> NodeCache::getCachedNodes(const InfoHash& id, sa_family_t sa_f, size_t count) { - const auto& c = (sa_f == AF_INET ? cache_4 : cache_6); + const auto& c = cache(sa_f); auto it_p = c.lower_bound(id), it_n = it_p; @@ -57,7 +57,7 @@ NodeCache::getCachedNodes(const InfoHash& id, sa_family_t sa_f, size_t count) { it_p = c.end(); if (auto n = it->second.lock()) - if ( not n->isExpired() ) + if ( not n->isExpired() and not n->isClient() ) nodes.emplace_back(std::move(n)); } @@ -71,7 +71,7 @@ NodeCache::clearBadNodes(sa_family_t family) clearBadNodes(AF_INET); clearBadNodes(AF_INET6); } else { - (family == AF_INET ? cache_4 : cache_6).clearBadNodes(); + cache(family).clearBadNodes(); } } @@ -88,12 +88,12 @@ NodeCache::NodeMap::getNode(const InfoHash& id) } std::shared_ptr -NodeCache::NodeMap::getNode(const InfoHash& id, const SockAddr& addr, time_point now, bool confirm) +NodeCache::NodeMap::getNode(const InfoHash& id, const SockAddr& addr, time_point now, bool confirm, bool client) { auto it = emplace(id, std::weak_ptr{}); auto node = it.first->second.lock(); if (not node) { - node = std::make_shared(id, addr); + node = std::make_shared(id, addr, client); it.first->second = node; } else if (confirm || node->time < now - Node::NODE_EXPIRE_TIME) { node->update(addr); diff --git a/src/parsed_message.h b/src/parsed_message.h index 83c74ab2..f2f691d6 100644 --- a/src/parsed_message.h +++ b/src/parsed_message.h @@ -43,6 +43,8 @@ struct ParsedMessage { InfoHash id; /* Network id */ NetId network {0}; + /** Is a client node */ + bool is_client {false}; /* hash for which values are requested */ InfoHash info_hash; /* target id around which to find nodes */ @@ -137,6 +139,9 @@ ParsedMessage::msgpack_unpack(msgpack::object msg) if (auto netid = findMapValue(msg, "n")) network = netid->as(); + if (auto is_client_v = findMapValue(msg, "s")) + is_client = is_client_v->as(); + std::string q; if (auto rq = findMapValue(msg, "q")) { if (rq->type != msgpack::type::STR)