summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0035-EventService-Fix-hostname-resolve-issue.patch
blob: 372ff68011982d852666aeb8f69a23ea24c8a1f1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
From c3a63a9ff4103b215d85845b98ba51c039511713 Mon Sep 17 00:00:00 2001
From: AppaRao Puli <apparao.puli@linux.intel.com>
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 <apparao.puli@linux.intel.com>
---
 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<HttpClient>
 {
   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<boost::beast::ssl_stream<boost::beast::tcp_stream&>> sslConn;
@@ -76,6 +80,32 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
     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<HttpClient>
         }
 
         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<HttpClient>
     {
         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<HttpClient>
                         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