From 6687d56910820013715168a2051b416839cc5430 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ben=20Gr=C3=A4f?= Date: Fri, 19 Oct 2018 10:35:01 +0200 Subject: [PATCH] Proper handling of DNS issues (#197) * Fixed dns resolver issues * fixed supported-variants in login --- src/net/BoostConnection.h | 2 +- src/net/Client.cpp | 47 ++++++++++++++++++++++++++++++++------- src/net/Client.h | 3 +++ src/net/Connection.cpp | 8 +++++++ src/net/Connection.h | 2 ++ 5 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/net/BoostConnection.h b/src/net/BoostConnection.h index 3e3b4855..058ee71f 100644 --- a/src/net/BoostConnection.h +++ b/src/net/BoostConnection.h @@ -65,7 +65,7 @@ public: m_socket.connect(endpointIterator, boost::bind(&BoostConnection::handleConnect, this->shared_from_this(), boost::asio::placeholders::error)); } else { - notifyError(std::string("[DNS resolve] ") + error.message()); + notifyDNSError(std::string("[DNS resolve] ") + error.message()); } } diff --git a/src/net/Client.cpp b/src/net/Client.cpp index b9300d06..c468114b 100644 --- a/src/net/Client.cpp +++ b/src/net/Client.cpp @@ -73,6 +73,7 @@ Client::Client(int id, const char *agent, IClientListener *listener) : uv_async_init(uv_default_loop(), &onConnectedAsync, Client::onConnected); uv_async_init(uv_default_loop(), &onReceivedAsync, Client::onReceived); uv_async_init(uv_default_loop(), &onErrorAsync, Client::onError); + uv_async_init(uv_default_loop(), &onDNSErrorAsync, Client::onDNSError); } @@ -96,7 +97,7 @@ void Client::connect(const Url *url) void Client::connect() { - LOG_DEBUG("connect"); + LOG_DEBUG("[%d] connect", m_id); m_connection = establishConnection(shared_from_this(), m_url.useTls() ? CONNECTION_TYPE_TLS : CONNECTION_TYPE_TCP, @@ -106,13 +107,15 @@ void Client::connect() void Client::disconnect() { - LOG_DEBUG("disconnect"); + LOG_DEBUG("[%d] disconnect", m_id); uv_timer_stop(&m_keepAliveTimer); m_expire = 0; m_failures = -1; + LOG_DEBUG("[%d] disconnect set m_failure to -1", m_id); + close(); } @@ -330,7 +333,7 @@ int64_t Client::send(char* buf, size_t size) void Client::close() { - LOG_DEBUG("close"); + LOG_DEBUG("[%d] close", m_id); if (m_connection) { m_connection->disconnect(); @@ -364,7 +367,8 @@ void Client::login() rapidjson::Value supportedPowVariantsList(rapidjson::kArrayType); for (auto& supportedPowVariant : getSupportedPowVariants()) { - supportedPowVariantsList.PushBack(rapidjson::StringRef(supportedPowVariant.c_str()), allocator); + rapidjson::Value val(supportedPowVariant.c_str(), allocator); + supportedPowVariantsList.PushBack(val, allocator); } params.AddMember("supported-variants", supportedPowVariantsList, allocator); @@ -517,7 +521,9 @@ void Client::parseResponse(int64_t id, const rapidjson::Value &result, const rap return reconnect(); } + LOG_DEBUG("[%d] login set m_failure to 0", m_id); m_failures = 0; + m_listener->onLoginSuccess(this); m_listener->onJobReceived(this, m_job); return; @@ -553,7 +559,7 @@ void Client::ping() void Client::reconnect() { - LOG_DEBUG("reconnect"); + LOG_DEBUG("[%d] reconnect", m_id); close(); @@ -562,11 +568,12 @@ void Client::reconnect() } if (m_failures == -1) { - LOG_DEBUG("reconnect -> m_failures == -1"); + LOG_DEBUG("[%d] reconnect -> m_failures == -1", m_id); return m_listener->onClose(this, -1); } m_failures++; + LOG_DEBUG("[%d] increment m_failures to: %d", m_id, m_failures); m_listener->onClose(this, (int) m_failures); m_expire = uv_now(uv_default_loop()) + m_retryPause; @@ -636,10 +643,9 @@ void Client::scheduleOnReceived(char* data, std::size_t size) void Client::onError(uv_async_t *handle) { - LOG_DEBUG("onError"); - auto client = getClient(handle->data); if (client) { + LOG_DEBUG("[%d] onError", client->m_id); client->reconnect(); } } @@ -655,3 +661,28 @@ void Client::scheduleOnError(const std::string &error) onErrorAsync.data = this; uv_async_send(&onErrorAsync); } + +void Client::onDNSError(uv_async_t *handle) +{ + auto client = getClient(handle->data); + if (client) { + if (client->m_failures == -1) { + client->m_failures = 0; + } + + LOG_DEBUG("[%d] onDNSError", client->m_id); + client->reconnect(); + } +} + +void Client::scheduleOnDNSError(const std::string &error) +{ + LOG_DEBUG("scheduleOnDNSError"); + + if (!m_quiet) { + LOG_ERR("[%s:%u] DNS Error: \"%s\"", m_url.host(), m_url.port(), error.c_str()); + } + + onDNSErrorAsync.data = this; + uv_async_send(&onDNSErrorAsync); +} diff --git a/src/net/Client.h b/src/net/Client.h index 03832b46..2cb5175b 100644 --- a/src/net/Client.h +++ b/src/net/Client.h @@ -72,6 +72,7 @@ public: static void onConnected(uv_async_t *handle); static void onReceived(uv_async_t *handle); static void onError(uv_async_t *handle); + static void onDNSError(uv_async_t *handle); private: bool isCriticalError(const char *message); @@ -92,6 +93,7 @@ private: virtual void scheduleOnConnected(); virtual void scheduleOnReceived(char *data, size_t size); virtual void scheduleOnError(const std::string &error); + virtual void scheduleOnDNSError(const std::string &error); static inline Client *getClient(void *data) { return static_cast(data); } @@ -122,6 +124,7 @@ private: uv_async_t onConnectedAsync; uv_async_t onReceivedAsync; uv_async_t onErrorAsync; + uv_async_t onDNSErrorAsync; uv_timer_t m_keepAliveTimer; diff --git a/src/net/Connection.cpp b/src/net/Connection.cpp index f65f5c84..a114b295 100644 --- a/src/net/Connection.cpp +++ b/src/net/Connection.cpp @@ -60,6 +60,14 @@ void Connection::notifyError(const std::string& error) } } +void Connection::notifyDNSError(const std::string& error) +{ + ConnectionListener::Ptr listener = listener_.lock(); + if (listener) + { + listener->scheduleOnDNSError(error); + } +} Connection::Ptr establishConnection(const ConnectionListener::Ptr& listener, ConnectionType type, const std::string& host, uint16_t port) diff --git a/src/net/Connection.h b/src/net/Connection.h index 5ecb9105..5e1d1081 100644 --- a/src/net/Connection.h +++ b/src/net/Connection.h @@ -39,6 +39,7 @@ public: virtual void scheduleOnConnected() = 0; virtual void scheduleOnReceived(char *data, std::size_t size) = 0; virtual void scheduleOnError(const std::string &error) = 0; + virtual void scheduleOnDNSError(const std::string &error) = 0; }; class Connection : private boost::noncopyable @@ -61,6 +62,7 @@ public: void notifyConnected(); void notifyRead(char* data, size_t size); void notifyError(const std::string& error); + void notifyDNSError(const std::string& error); private: ConnectionListener::WeakPtr listener_;