From c3a63a9ff4103b215d85845b98ba51c039511713 Mon Sep 17 00:00:00 2001 From: AppaRao Puli Date: Fri, 16 Oct 2020 17:03:36 +0530 Subject: [PATCH] EventService - Fix hostname resolve issue The hostname also accepted in EventService as destination. When this hostname resolution fails, causes the bmcweb crash. So avoid the bmcweb crash by catching exception and control goes to retry process like any other failure. Tested: - No bmcweb crash observed when hostname resolve fails. - Created subscription with invalid hostname and verified the retry process. - Created subscriptions with positive cases and all works fine. Change-Id: I0adf6864911c4cf49a11110519c73556d87f3279 Signed-off-by: AppaRao Puli --- http/http_client.hpp | 54 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/http/http_client.hpp b/http/http_client.hpp index 6d3d702..abccc84 100644 --- a/http/http_client.hpp +++ b/http/http_client.hpp @@ -36,6 +36,9 @@ static constexpr unsigned int httpReadBodyLimit = 1024; enum class ConnState { initialized, + resolveInProgress, + resolveFailed, + resolved, connectInProgress, connectFailed, sslHandshakeInProgress, @@ -52,6 +55,7 @@ enum class ConnState class HttpClient : public std::enable_shared_from_this { private: + boost::asio::ip::tcp::resolver resolver; boost::asio::ssl::context ctx{boost::asio::ssl::context::tlsv12_client}; boost::beast::tcp_stream conn; std::optional> sslConn; @@ -76,6 +80,32 @@ class HttpClient : public std::enable_shared_from_this bool runningTimer; ConnState state; + void doResolve() + { + BMCWEB_LOG_DEBUG << "Trying to resolve: " << host << ":" << port; + if (state == ConnState::resolveInProgress) + { + return; + } + state = ConnState::resolveInProgress; + // TODO: Use async_resolver. boost asio example + // code as is crashing with async_resolve(). + try + { + endpoint = resolver.resolve(host, port); + } + catch (const std::exception& e) + { + BMCWEB_LOG_ERROR << "Failed to resolve hostname: " << host << " - " + << e.what(); + state = ConnState::resolveFailed; + checkQueue(); + return; + } + state = ConnState::resolved; + checkQueue(); + } + void doConnect() { if (useSsl) @@ -348,6 +378,7 @@ class HttpClient : public std::enable_shared_from_this } if ((state == ConnState::connectFailed) || + (state == ConnState::resolveFailed) || (state == ConnState::sendFailed) || (state == ConnState::recvFailed)) { @@ -393,16 +424,21 @@ class HttpClient : public std::enable_shared_from_this { switch (state) { + case ConnState::initialized: + case ConnState::resolveFailed: + case ConnState::connectFailed: + doResolve(); + break; case ConnState::connectInProgress: + case ConnState::resolveInProgress: case ConnState::sslHandshakeInProgress: case ConnState::sendInProgress: case ConnState::suspended: case ConnState::terminated: // do nothing break; - case ConnState::initialized: case ConnState::closed: - case ConnState::connectFailed: + case ConnState::resolved: case ConnState::sendFailed: case ConnState::recvFailed: { @@ -428,18 +464,12 @@ class HttpClient : public std::enable_shared_from_this const std::string& destIP, const std::string& destPort, const std::string& destUri, const bool inUseSsl = true) : - conn(ioc), - timer(ioc), subId(id), host(destIP), port(destPort), uri(destUri), - useSsl(inUseSsl), retryCount(0), maxRetryAttempts(5), + resolver(ioc), + conn(ioc), timer(ioc), subId(id), host(destIP), port(destPort), + uri(destUri), useSsl(inUseSsl), retryCount(0), maxRetryAttempts(5), retryPolicyAction("TerminateAfterRetries"), runningTimer(false), state(ConnState::initialized) - { - boost::asio::ip::tcp::resolver resolver(ioc); - // TODO: Use async_resolver. boost asio example - // code as is crashing with async_resolve(). - // It needs debug. - endpoint = resolver.resolve(host, port); - } + {} void sendData(const std::string& data) { -- 2.7.4