Proper handling of DNS issues (#197)

* Fixed dns resolver issues
* fixed supported-variants in login
This commit is contained in:
Ben Gräf 2018-10-19 10:35:01 +02:00 committed by GitHub
parent 0d2f4d1c7a
commit 6687d56910
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 53 additions and 9 deletions

View file

@ -65,7 +65,7 @@ public:
m_socket.connect(endpointIterator, boost::bind(&BoostConnection::handleConnect, this->shared_from_this(), m_socket.connect(endpointIterator, boost::bind(&BoostConnection::handleConnect, this->shared_from_this(),
boost::asio::placeholders::error)); boost::asio::placeholders::error));
} else { } else {
notifyError(std::string("[DNS resolve] ") + error.message()); notifyDNSError(std::string("[DNS resolve] ") + error.message());
} }
} }

View file

@ -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(), &onConnectedAsync, Client::onConnected);
uv_async_init(uv_default_loop(), &onReceivedAsync, Client::onReceived); uv_async_init(uv_default_loop(), &onReceivedAsync, Client::onReceived);
uv_async_init(uv_default_loop(), &onErrorAsync, Client::onError); 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() void Client::connect()
{ {
LOG_DEBUG("connect"); LOG_DEBUG("[%d] connect", m_id);
m_connection = establishConnection(shared_from_this(), m_connection = establishConnection(shared_from_this(),
m_url.useTls() ? CONNECTION_TYPE_TLS : CONNECTION_TYPE_TCP, m_url.useTls() ? CONNECTION_TYPE_TLS : CONNECTION_TYPE_TCP,
@ -106,13 +107,15 @@ void Client::connect()
void Client::disconnect() void Client::disconnect()
{ {
LOG_DEBUG("disconnect"); LOG_DEBUG("[%d] disconnect", m_id);
uv_timer_stop(&m_keepAliveTimer); uv_timer_stop(&m_keepAliveTimer);
m_expire = 0; m_expire = 0;
m_failures = -1; m_failures = -1;
LOG_DEBUG("[%d] disconnect set m_failure to -1", m_id);
close(); close();
} }
@ -330,7 +333,7 @@ int64_t Client::send(char* buf, size_t size)
void Client::close() void Client::close()
{ {
LOG_DEBUG("close"); LOG_DEBUG("[%d] close", m_id);
if (m_connection) { if (m_connection) {
m_connection->disconnect(); m_connection->disconnect();
@ -364,7 +367,8 @@ void Client::login()
rapidjson::Value supportedPowVariantsList(rapidjson::kArrayType); rapidjson::Value supportedPowVariantsList(rapidjson::kArrayType);
for (auto& supportedPowVariant : getSupportedPowVariants()) { 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); params.AddMember("supported-variants", supportedPowVariantsList, allocator);
@ -517,7 +521,9 @@ void Client::parseResponse(int64_t id, const rapidjson::Value &result, const rap
return reconnect(); return reconnect();
} }
LOG_DEBUG("[%d] login set m_failure to 0", m_id);
m_failures = 0; m_failures = 0;
m_listener->onLoginSuccess(this); m_listener->onLoginSuccess(this);
m_listener->onJobReceived(this, m_job); m_listener->onJobReceived(this, m_job);
return; return;
@ -553,7 +559,7 @@ void Client::ping()
void Client::reconnect() void Client::reconnect()
{ {
LOG_DEBUG("reconnect"); LOG_DEBUG("[%d] reconnect", m_id);
close(); close();
@ -562,11 +568,12 @@ void Client::reconnect()
} }
if (m_failures == -1) { 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); return m_listener->onClose(this, -1);
} }
m_failures++; m_failures++;
LOG_DEBUG("[%d] increment m_failures to: %d", m_id, m_failures);
m_listener->onClose(this, (int) m_failures); m_listener->onClose(this, (int) m_failures);
m_expire = uv_now(uv_default_loop()) + m_retryPause; 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) void Client::onError(uv_async_t *handle)
{ {
LOG_DEBUG("onError");
auto client = getClient(handle->data); auto client = getClient(handle->data);
if (client) { if (client) {
LOG_DEBUG("[%d] onError", client->m_id);
client->reconnect(); client->reconnect();
} }
} }
@ -655,3 +661,28 @@ void Client::scheduleOnError(const std::string &error)
onErrorAsync.data = this; onErrorAsync.data = this;
uv_async_send(&onErrorAsync); 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);
}

View file

@ -72,6 +72,7 @@ public:
static void onConnected(uv_async_t *handle); static void onConnected(uv_async_t *handle);
static void onReceived(uv_async_t *handle); static void onReceived(uv_async_t *handle);
static void onError(uv_async_t *handle); static void onError(uv_async_t *handle);
static void onDNSError(uv_async_t *handle);
private: private:
bool isCriticalError(const char *message); bool isCriticalError(const char *message);
@ -92,6 +93,7 @@ private:
virtual void scheduleOnConnected(); virtual void scheduleOnConnected();
virtual void scheduleOnReceived(char *data, size_t size); virtual void scheduleOnReceived(char *data, size_t size);
virtual void scheduleOnError(const std::string &error); virtual void scheduleOnError(const std::string &error);
virtual void scheduleOnDNSError(const std::string &error);
static inline Client *getClient(void *data) { return static_cast<Client*>(data); } static inline Client *getClient(void *data) { return static_cast<Client*>(data); }
@ -122,6 +124,7 @@ private:
uv_async_t onConnectedAsync; uv_async_t onConnectedAsync;
uv_async_t onReceivedAsync; uv_async_t onReceivedAsync;
uv_async_t onErrorAsync; uv_async_t onErrorAsync;
uv_async_t onDNSErrorAsync;
uv_timer_t m_keepAliveTimer; uv_timer_t m_keepAliveTimer;

View file

@ -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, Connection::Ptr establishConnection(const ConnectionListener::Ptr& listener,
ConnectionType type, const std::string& host, uint16_t port) ConnectionType type, const std::string& host, uint16_t port)

View file

@ -39,6 +39,7 @@ public:
virtual void scheduleOnConnected() = 0; virtual void scheduleOnConnected() = 0;
virtual void scheduleOnReceived(char *data, std::size_t size) = 0; virtual void scheduleOnReceived(char *data, std::size_t size) = 0;
virtual void scheduleOnError(const std::string &error) = 0; virtual void scheduleOnError(const std::string &error) = 0;
virtual void scheduleOnDNSError(const std::string &error) = 0;
}; };
class Connection : private boost::noncopyable class Connection : private boost::noncopyable
@ -61,6 +62,7 @@ public:
void notifyConnected(); void notifyConnected();
void notifyRead(char* data, size_t size); void notifyRead(char* data, size_t size);
void notifyError(const std::string& error); void notifyError(const std::string& error);
void notifyDNSError(const std::string& error);
private: private:
ConnectionListener::WeakPtr listener_; ConnectionListener::WeakPtr listener_;