From 87cf6faedd4b2747f11da456197bd5eda0d6fbb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20D=C3=A9saulniers?= <sim.desaulniers@gmail.com> Date: Wed, 21 Sep 2016 15:14:59 -0400 Subject: [PATCH] dht/node: don't allow more than 3 auth errors --- include/opendht/node.h | 16 ++++++++++++++++ src/dht.cpp | 7 ++++--- src/network_engine.cpp | 3 +++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/include/opendht/node.h b/include/opendht/node.h index 5ecb9a61..14e8ae7c 100644 --- a/include/opendht/node.h +++ b/include/opendht/node.h @@ -50,6 +50,18 @@ struct Node { std::string getAddrStr() const { return addr.toString(); } + + /** + * Makes notice about an additionnal authentication error with this node. Up + * to MAX_AUTH_ERRORS errors are accepted in order to let the node recover. + * Upon this limit, the node expires. + */ + void authError() { + if (++auth_errors > MAX_AUTH_ERRORS) + setExpired(); + } + void authSuccess() { auth_errors = 0; } + bool isExpired() const { return expired_; } bool isGood(time_point now) const; bool isPendingMessage() const; @@ -83,7 +95,11 @@ struct Node { static constexpr const std::chrono::seconds MAX_RESPONSE_TIME {1}; private: + /* Number of times we accept authentication errors from this node. */ + static const constexpr unsigned MAX_AUTH_ERRORS {3}; + std::list<std::weak_ptr<Request>> requests_ {}; + unsigned auth_errors {0}; bool expired_ {false}; void clearPendingQueue() { diff --git a/src/dht.cpp b/src/dht.cpp index e7f9f803..c1550185 100644 --- a/src/dht.cpp +++ b/src/dht.cpp @@ -408,9 +408,9 @@ struct Dht::SearchNode { or not gs->second or not gs->second->pending())) return time_point::min(); return ((gs != getStatus.cend() and gs->second and gs->second->pending()) - or ack == acked.cend() or not ack->second or ack->second->pending()) ? - time_point::max() : - ack->second->reply_time + type.expiration - REANNOUNCE_MARGIN; + or ack == acked.cend() or not ack->second or ack->second->pending()) + ? time_point::max() + : ack->second->reply_time + type.expiration - REANNOUNCE_MARGIN; } /** @@ -3000,6 +3000,7 @@ void Dht::onError(std::shared_ptr<Request> req, DhtProtocolException e) { if (e.getCode() == DhtProtocolException::UNAUTHORIZED) { DHT_LOG.ERR("[node %s] token flush", req->node->toString().c_str()); + req->node->authError(); network_engine.cancelRequest(req); for (auto& srp : req->node->getFamily() == AF_INET ? searches4 : searches6) { auto& sr = srp.second; diff --git a/src/network_engine.cpp b/src/network_engine.cpp index f0e8c401..4ada3962 100644 --- a/src/network_engine.cpp +++ b/src/network_engine.cpp @@ -377,6 +377,9 @@ NetworkEngine::processMessage(const uint8_t *buf, size_t buflen, const SockAddr& break; } case MessageType::Reply: + if (msg.type == MessageType::AnnounceValue or msg.type == MessageType::Listen) + req->node->authSuccess(); + // erase before calling callback to make sure iterator is still valid if (not req->persistent) requests.erase(reqp); -- GitLab