summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0001-Add-unmerged-changes-for-http-retry-support.patch121
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0001-EventService-Fix-retry-handling-for-http-client.patch546
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0002-EventService-https-client-support.patch166
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0004-Add-Server-Sent-Events-support.patch56
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0005-Add-SSE-style-subscription-support-to-eventservice.patch50
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0006-Add-EventService-SSE-filter-support.patch18
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0010-Remove-Terminated-Event-Subscriptions.patch34
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0011-Fix-bmcweb-crash-while-deleting-terminated-subscriptions.patch141
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/README28
9 files changed, 462 insertions, 698 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0001-Add-unmerged-changes-for-http-retry-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0001-Add-unmerged-changes-for-http-retry-support.patch
new file mode 100644
index 000000000..52135e255
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0001-Add-unmerged-changes-for-http-retry-support.patch
@@ -0,0 +1,121 @@
+From 6ff897d2b5513f15445f18aae16d8439ed94f377 Mon Sep 17 00:00:00 2001
+From: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com>
+Date: Mon, 11 Oct 2021 18:41:27 +0530
+Subject: [PATCH] Add unmerged changes for http retry support
+
+The http retry support added upstream as a single patch was slpit into
+3 patches, but only 2 of them was merged.
+This commit pulls in the differentail changes required to complete the
+entire http retry support. and also allow for other subsequent patches
+to be appplied easily.
+
+Change-Id: Id8ccd991b7ffc505196b1a92b23e1cd51e00bc89
+Signed-off-by: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com>
+---
+ http/http_client.hpp | 44 +++++++++++--------
+ .../include/event_service_manager.hpp | 2 +-
+ 2 files changed, 27 insertions(+), 19 deletions(-)
+
+diff --git a/http/http_client.hpp b/http/http_client.hpp
+index ab20eb0..aad1cce 100644
+--- a/http/http_client.hpp
++++ b/http/http_client.hpp
+@@ -68,7 +68,6 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ std::optional<
+ boost::beast::http::response_parser<boost::beast::http::string_body>>
+ parser;
+- std::vector<std::pair<std::string, std::string>> headers;
+ boost::circular_buffer_space_optimized<std::string> requestDataQueue{};
+
+ ConnState state;
+@@ -137,18 +136,6 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+
+ BMCWEB_LOG_DEBUG << __FUNCTION__ << "(): " << host << ":" << port;
+
+- req.version(static_cast<int>(11)); // HTTP 1.1
+- req.target(uri);
+- req.method(boost::beast::http::verb::post);
+-
+- // Set headers
+- for (const auto& [key, value] : headers)
+- {
+- req.set(key, value);
+- }
+- req.set(boost::beast::http::field::host, host);
+- req.keep_alive(true);
+-
+ req.body() = data;
+ req.prepare_payload();
+
+@@ -204,6 +191,17 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ BMCWEB_LOG_DEBUG << "recvMessage() data: "
+ << self->parser->get();
+
++ // Check if the response and header are received
++ if (!self->parser->is_done())
++ {
++ // The parser failed to receive the response
++ BMCWEB_LOG_ERROR
++ << "recvMessage() parser failed to receive response";
++ self->state = ConnState::recvFailed;
++ self->handleConnState();
++ return;
++ }
++
+ unsigned int respCode = self->parser->get().result_int();
+ BMCWEB_LOG_DEBUG << "recvMessage() Header Response Code: "
+ << respCode;
+@@ -398,11 +396,17 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ const std::string& destIP, const std::string& destPort,
+ const std::string& destUri) :
+ conn(ioc),
+- timer(ioc), subId(id), host(destIP), port(destPort), uri(destUri),
+- retryCount(0), maxRetryAttempts(5), retryIntervalSecs(0),
++ timer(ioc), req(boost::beast::http::verb::post, destUri, 11),
++ state(ConnState::initialized), subId(id), host(destIP), port(destPort),
++ uri(destUri), retryCount(0), maxRetryAttempts(5), retryIntervalSecs(0),
+ retryPolicyAction("TerminateAfterRetries"), runningTimer(false)
+ {
+- state = ConnState::initialized;
++ // Set the request header
++ req.set(boost::beast::http::field::host, host);
++ req.set(boost::beast::http::field::content_type, "application/json");
++ req.keep_alive(true);
++
++ requestDataQueue.set_capacity(maxRequestQueueSize);
+ }
+
+ void sendData(const std::string& data)
+@@ -425,10 +429,14 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ return;
+ }
+
+- void setHeaders(
++ void addHeaders(
+ const std::vector<std::pair<std::string, std::string>>& httpHeaders)
+ {
+- headers = httpHeaders;
++ // Set custom headers
++ for (const auto& [key, value] : httpHeaders)
++ {
++ req.set(key, value);
++ }
+ }
+
+ void setRetryConfig(const uint32_t retryAttempts,
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index 8042803..0a63b8c 100644
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -412,7 +412,7 @@ class Subscription : public persistent_data::UserSubscription
+ reqHeaders.emplace_back(std::pair(key, val));
+ }
+ }
+- conn->setHeaders(reqHeaders);
++ conn->addHeaders(reqHeaders);
+ conn->sendData(msg);
+ this->eventSeqNum++;
+ }
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0001-EventService-Fix-retry-handling-for-http-client.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0001-EventService-Fix-retry-handling-for-http-client.patch
deleted file mode 100644
index 7a6818008..000000000
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0001-EventService-Fix-retry-handling-for-http-client.patch
+++ /dev/null
@@ -1,546 +0,0 @@
-From f74393a9bca899e353be3d0e2dc5c224539fe432 Mon Sep 17 00:00:00 2001
-From: Sunitha Harish <sunithaharish04@gmail.com>
-Date: Fri, 19 Feb 2021 13:38:31 +0530
-Subject: [PATCH] EventService : Fix retry handling for http-client
-
-When the event send/receive is failed, the bmcweb does not handle
-the failure to tear-down the complete connection and start a fresh
-
-The keep-alive header from the event listener is read to update
-the connection states, so that the connection will be kept alive
-or closed as per the subscriber's specifications
-
-Updated the connection state machine to handle retry logic properly.
-Avoided multiple simultaneous async calls which crashes the bmcweb. So
-added connBusy flag which protects simultaneous async calls.
-
-Used boost http response parser as parser for producing the response
-message. Set the parser skip option to handle the empty response message
-from listening server.
-
-Tested by:
- - Subscribe for the events at BMC using DMTF event listener
- - Generate an event and see the same is received at the listener's console
- - Update the listner to change the keep-alive to true/false and
- observe the http-client connection states at bmcweb
- - Changed listener client to return non success HTTP status code
- and observed retry logic gets trigrred in http-client.
- - Gave wrong fqdn and observed async resolve failure and retry logc.
- - Stopped listener after connect and verified timeouts on http-client
- side.
-
-Change-Id: Ibb45691f139916ba2954da37beda9d4f91c7cef3
-Signed-off-by: Sunitha Harish <sunithaharish04@gmail.com>
-Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
----
- http/http_client.hpp | 288 ++++++++++--------
- .../include/event_service_manager.hpp | 2 +-
- 2 files changed, 162 insertions(+), 128 deletions(-)
-
-diff --git a/http/http_client.hpp b/http/http_client.hpp
-index 992ac2b..feabbba 100644
---- a/http/http_client.hpp
-+++ b/http/http_client.hpp
-@@ -34,22 +34,28 @@ namespace crow
- {
-
- static constexpr uint8_t maxRequestQueueSize = 50;
-+static constexpr unsigned int httpReadBodyLimit = 8192;
-
- enum class ConnState
- {
- initialized,
- resolveInProgress,
- resolveFailed,
-+ resolved,
- connectInProgress,
- connectFailed,
- connected,
- sendInProgress,
- sendFailed,
-+ recvInProgress,
- recvFailed,
- idle,
-- suspended,
-+ closeInProgress,
- closed,
-- terminated
-+ suspended,
-+ terminated,
-+ abortConnection,
-+ retry
- };
-
- class HttpClient : public std::enable_shared_from_this<HttpClient>
-@@ -58,11 +64,13 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
- crow::async_resolve::Resolver resolver;
- boost::beast::tcp_stream conn;
- boost::asio::steady_timer timer;
-- boost::beast::flat_buffer buffer;
-+ boost::beast::flat_static_buffer<httpReadBodyLimit> buffer;
- boost::beast::http::request<boost::beast::http::string_body> req;
-- boost::beast::http::response<boost::beast::http::string_body> res;
-- std::vector<std::pair<std::string, std::string>> headers;
-- std::queue<std::string> requestDataQueue;
-+ std::optional<
-+ boost::beast::http::response_parser<boost::beast::http::string_body>>
-+ parser;
-+ boost::circular_buffer_space_optimized<std::string> requestDataQueue{};
-+ std::vector<boost::asio::ip::tcp::endpoint> endPoints;
- ConnState state;
- std::string subId;
- std::string host;
-@@ -76,12 +84,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
-
- void doResolve()
- {
-- if (state == ConnState::resolveInProgress)
-- {
-- return;
-- }
- state = ConnState::resolveInProgress;
--
- BMCWEB_LOG_DEBUG << "Trying to resolve: " << host << ":" << port;
-
- auto respHandler =
-@@ -89,78 +92,56 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
- const boost::beast::error_code ec,
- const std::vector<boost::asio::ip::tcp::endpoint>&
- endpointList) {
-- if (ec)
-+ if (ec || (endpointList.size() == 0))
- {
- BMCWEB_LOG_ERROR << "Resolve failed: " << ec.message();
- self->state = ConnState::resolveFailed;
-- self->checkQueue();
-+ self->handleConnState();
- return;
- }
- BMCWEB_LOG_DEBUG << "Resolved";
-- self->doConnect(endpointList);
-+ self->endPoints.assign(endpointList.begin(),
-+ endpointList.end());
-+ self->state = ConnState::resolved;
-+ self->handleConnState();
- };
- resolver.asyncResolve(host, port, std::move(respHandler));
- }
-
-- void doConnect(
-- const std::vector<boost::asio::ip::tcp::endpoint>& endpointList)
-+ void doConnect()
- {
-- if (state == ConnState::connectInProgress)
-- {
-- return;
-- }
- state = ConnState::connectInProgress;
-
- BMCWEB_LOG_DEBUG << "Trying to connect to: " << host << ":" << port;
-
- conn.expires_after(std::chrono::seconds(30));
- conn.async_connect(
-- endpointList, [self(shared_from_this())](
-- const boost::beast::error_code ec,
-- const boost::asio::ip::tcp::endpoint& endpoint) {
-+ endPoints, [self(shared_from_this())](
-+ const boost::beast::error_code ec,
-+ const boost::asio::ip::tcp::endpoint& endpoint) {
- if (ec)
- {
- BMCWEB_LOG_ERROR << "Connect " << endpoint
- << " failed: " << ec.message();
- self->state = ConnState::connectFailed;
-- self->checkQueue();
-+ self->handleConnState();
- return;
- }
-- self->state = ConnState::connected;
- BMCWEB_LOG_DEBUG << "Connected to: " << endpoint;
--
-- self->checkQueue();
-+ self->state = ConnState::connected;
-+ self->handleConnState();
- });
- }
-
- void sendMessage(const std::string& data)
- {
-- if (state == ConnState::sendInProgress)
-- {
-- return;
-- }
- state = ConnState::sendInProgress;
-
- BMCWEB_LOG_DEBUG << __FUNCTION__ << "(): " << host << ":" << port;
-
-- req.version(static_cast<int>(11)); // HTTP 1.1
-- req.target(uri);
-- req.method(boost::beast::http::verb::post);
--
-- // Set headers
-- for (const auto& [key, value] : headers)
-- {
-- req.set(key, value);
-- }
-- req.set(boost::beast::http::field::host, host);
-- req.keep_alive(true);
--
- req.body() = data;
- req.prepare_payload();
-
-- // Set a timeout on the operation
-- conn.expires_after(std::chrono::seconds(30));
--
- // Send the HTTP request to the remote host
- boost::beast::http::async_write(
- conn, req,
-@@ -171,7 +152,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
- BMCWEB_LOG_ERROR << "sendMessage() failed: "
- << ec.message();
- self->state = ConnState::sendFailed;
-- self->checkQueue();
-+ self->handleConnState();
- return;
- }
- BMCWEB_LOG_DEBUG << "sendMessage() bytes transferred: "
-@@ -184,9 +165,17 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
-
- void recvMessage()
- {
-+ state = ConnState::recvInProgress;
-+
-+ parser.emplace(std::piecewise_construct, std::make_tuple());
-+ parser->body_limit(httpReadBodyLimit);
-+
-+ // Check only for the response header
-+ parser->skip(true);
-+
- // Receive the HTTP response
- boost::beast::http::async_read(
-- conn, buffer, res,
-+ conn, buffer, *parser,
- [self(shared_from_this())](const boost::beast::error_code& ec,
- const std::size_t& bytesTransferred) {
- if (ec)
-@@ -194,30 +183,47 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
- BMCWEB_LOG_ERROR << "recvMessage() failed: "
- << ec.message();
- self->state = ConnState::recvFailed;
-- self->checkQueue();
-+ self->handleConnState();
- return;
- }
- BMCWEB_LOG_DEBUG << "recvMessage() bytes transferred: "
- << bytesTransferred;
-- boost::ignore_unused(bytesTransferred);
--
-- // Discard received data. We are not interested.
-- BMCWEB_LOG_DEBUG << "recvMessage() data: " << self->res;
-+ BMCWEB_LOG_DEBUG << "recvMessage() data: "
-+ << self->parser->get();
-
- // Send is successful, Lets remove data from queue
- // check for next request data in queue.
-- self->requestDataQueue.pop();
-+ if (!self->requestDataQueue.empty())
-+ {
-+ self->requestDataQueue.pop_front();
-+ }
- self->state = ConnState::idle;
-- self->checkQueue();
-+
-+ // Keep the connection alive if server supports it
-+ // Else close the connection
-+ BMCWEB_LOG_DEBUG << "recvMessage() keepalive : "
-+ << self->parser->keep_alive();
-+ if (!self->parser->keep_alive())
-+ {
-+ // Abort the connection since server is not keep-alive
-+ // enabled
-+ self->state = ConnState::abortConnection;
-+ }
-+
-+ // Returns ownership of the parsed message
-+ self->parser->release();
-+
-+ self->handleConnState();
- });
- }
-
- void doClose()
- {
-+ state = ConnState::closeInProgress;
- boost::beast::error_code ec;
- conn.socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
-+ conn.close();
-
-- state = ConnState::closed;
- // not_connected happens sometimes so don't bother reporting it.
- if (ec && ec != boost::beast::errc::not_connected)
- {
-@@ -225,112 +231,139 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
- return;
- }
- BMCWEB_LOG_DEBUG << "Connection closed gracefully";
-- }
--
-- void checkQueue(const bool newRecord = false)
-- {
-- if (requestDataQueue.empty())
-+ if ((state != ConnState::suspended) && (state != ConnState::terminated))
- {
-- // TODO: Having issue in keeping connection alive. So lets close if
-- // nothing to be transferred.
-- doClose();
--
-- BMCWEB_LOG_DEBUG << "requestDataQueue is empty\n";
-- return;
-+ state = ConnState::closed;
-+ handleConnState();
- }
-+ }
-
-+ void waitAndRetry()
-+ {
- if (retryCount >= maxRetryAttempts)
- {
-- BMCWEB_LOG_ERROR << "Maximum number of retries is reached.";
-+ BMCWEB_LOG_ERROR << "Maximum number of retries reached.";
-
- // Clear queue.
- while (!requestDataQueue.empty())
- {
-- requestDataQueue.pop();
-+ requestDataQueue.pop_front();
- }
-
-- BMCWEB_LOG_DEBUG << "Retry policy is set to " << retryPolicyAction;
-+ BMCWEB_LOG_DEBUG << "Retry policy: " << retryPolicyAction;
- if (retryPolicyAction == "TerminateAfterRetries")
- {
- // TODO: delete subscription
- state = ConnState::terminated;
-- return;
- }
- if (retryPolicyAction == "SuspendRetries")
- {
- state = ConnState::suspended;
-- return;
- }
-- // keep retrying, reset count and continue.
-+ // Reset the retrycount to zero so that client can try connecting
-+ // again if needed
- retryCount = 0;
-+ handleConnState();
-+ return;
- }
-
-- if ((state == ConnState::connectFailed) ||
-- (state == ConnState::sendFailed) ||
-- (state == ConnState::recvFailed))
-+ if (runningTimer)
- {
-- if (newRecord)
-- {
-- // We are already running async wait and retry.
-- // Since record is added to queue, it gets the
-- // turn in FIFO.
-- return;
-- }
--
-- if (runningTimer)
-- {
-- BMCWEB_LOG_DEBUG << "Retry timer is already running.";
-- return;
-- }
-- runningTimer = true;
--
-- retryCount++;
--
-- BMCWEB_LOG_DEBUG << "Attempt retry after " << retryIntervalSecs
-- << " seconds. RetryCount = " << retryCount;
-- timer.expires_after(std::chrono::seconds(retryIntervalSecs));
-- timer.async_wait(
-- [self = shared_from_this()](const boost::system::error_code&) {
-- self->runningTimer = false;
-- self->connStateCheck();
-- });
-+ BMCWEB_LOG_DEBUG << "Retry timer is already running.";
- return;
- }
-- // reset retry count.
-- retryCount = 0;
-- connStateCheck();
-+ runningTimer = true;
-+
-+ retryCount++;
-+
-+ BMCWEB_LOG_DEBUG << "Attempt retry after " << retryIntervalSecs
-+ << " seconds. RetryCount = " << retryCount;
-+ timer.expires_after(std::chrono::seconds(retryIntervalSecs));
-+ timer.async_wait(
-+ [self = shared_from_this()](const boost::system::error_code ec) {
-+ if (ec)
-+ {
-+ BMCWEB_LOG_ERROR << "async_wait failed: " << ec.message();
-+ // Ignore the error and continue the retry loop to attempt
-+ // sending the event as per the retry policy
-+ }
-+ self->runningTimer = false;
-
-+ // Lets close connection and start from resolve.
-+ self->doClose();
-+ });
- return;
- }
-
-- void connStateCheck()
-+ void handleConnState()
- {
- switch (state)
- {
- case ConnState::resolveInProgress:
- case ConnState::connectInProgress:
- case ConnState::sendInProgress:
-- case ConnState::suspended:
-- case ConnState::terminated:
-- // do nothing
-+ case ConnState::recvInProgress:
-+ case ConnState::closeInProgress:
-+ {
-+ BMCWEB_LOG_DEBUG << "Async operation is already in progress";
- break;
-+ }
- case ConnState::initialized:
- case ConnState::closed:
-+ {
-+ if (requestDataQueue.empty())
-+ {
-+ BMCWEB_LOG_DEBUG << "requestDataQueue is empty";
-+ return;
-+ }
-+ doResolve();
-+ break;
-+ }
-+ case ConnState::resolved:
-+ {
-+ doConnect();
-+ break;
-+ }
-+ case ConnState::suspended:
-+ case ConnState::terminated:
-+ {
-+ doClose();
-+ break;
-+ }
-+ case ConnState::resolveFailed:
- case ConnState::connectFailed:
- case ConnState::sendFailed:
- case ConnState::recvFailed:
-- case ConnState::resolveFailed:
-+ case ConnState::retry:
- {
-- doResolve();
-+ // In case of failures during connect and handshake
-+ // the retry policy will be applied
-+ waitAndRetry();
- break;
- }
- case ConnState::connected:
- case ConnState::idle:
- {
-+ // State idle means, previous attempt is successful
-+ // State connected means, client connection is established
-+ // successfully
-+ if (requestDataQueue.empty())
-+ {
-+ BMCWEB_LOG_DEBUG << "requestDataQueue is empty";
-+ return;
-+ }
- std::string data = requestDataQueue.front();
- sendMessage(data);
- break;
- }
-+ case ConnState::abortConnection:
-+ {
-+ // Server did not want to keep alive the session
-+ doClose();
-+ break;
-+ }
-+ default:
-+ break;
- }
- }
-
-@@ -339,37 +372,38 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
- const std::string& destIP, const std::string& destPort,
- const std::string& destUri) :
- conn(ioc),
-- timer(ioc), subId(id), host(destIP), port(destPort), uri(destUri),
-- retryCount(0), maxRetryAttempts(5), retryIntervalSecs(0),
-+ timer(ioc), req(boost::beast::http::verb::post, destUri, 11),
-+ state(ConnState::initialized), subId(id), host(destIP), port(destPort),
-+ uri(destUri), retryCount(0), maxRetryAttempts(5), retryIntervalSecs(0),
- retryPolicyAction("TerminateAfterRetries"), runningTimer(false)
- {
-- state = ConnState::initialized;
-+ // Set the request header
-+ req.set(boost::beast::http::field::host, host);
-+ req.set(boost::beast::http::field::content_type, "application/json");
-+ req.keep_alive(true);
-+
-+ requestDataQueue.set_capacity(maxRequestQueueSize);
- }
-
- void sendData(const std::string& data)
- {
-- if (state == ConnState::suspended)
-+ if ((state == ConnState::suspended) || (state == ConnState::terminated))
- {
- return;
- }
--
-- if (requestDataQueue.size() <= maxRequestQueueSize)
-- {
-- requestDataQueue.push(data);
-- checkQueue(true);
-- }
-- else
-- {
-- BMCWEB_LOG_ERROR << "Request queue is full. So ignoring data.";
-- }
--
-+ requestDataQueue.push_back(data);
-+ handleConnState();
- return;
- }
-
-- void setHeaders(
-+ void addHeaders(
- const std::vector<std::pair<std::string, std::string>>& httpHeaders)
- {
-- headers = httpHeaders;
-+ // Set custom headers
-+ for (const auto& [key, value] : httpHeaders)
-+ {
-+ req.set(key, value);
-+ }
- }
-
- void setRetryConfig(const uint32_t retryAttempts,
-diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
-index 11190ef..a8f7517 100644
---- a/redfish-core/include/event_service_manager.hpp
-+++ b/redfish-core/include/event_service_manager.hpp
-@@ -422,7 +422,7 @@ class Subscription
- reqHeaders.emplace_back(std::pair(key, val));
- }
- }
-- conn->setHeaders(reqHeaders);
-+ conn->addHeaders(reqHeaders);
- conn->sendData(msg);
- this->eventSeqNum++;
- }
---
-2.25.1
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0002-EventService-https-client-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0002-EventService-https-client-support.patch
index eef0ff065..aeeafc421 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0002-EventService-https-client-support.patch
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0002-EventService-https-client-support.patch
@@ -1,28 +1,27 @@
-From 4df4a36d6d2cc11c51cc9d53cd441178cc97e39b Mon Sep 17 00:00:00 2001
+From 3f2ad28e6e124249cde3df50c9e18c283fbcbf3e Mon Sep 17 00:00:00 2001
From: AppaRao Puli <apparao.puli@linux.intel.com>
Date: Mon, 22 Feb 2021 17:07:47 +0000
Subject: [PATCH] EventService: https client support
-Add https client support for push style
-eventing. Using this BMC can push the event
-logs/telemetry data to event listener over
-secure http channel.
+Add https client support for push style eventing. Using this BMC can
+push the event logs/telemetry data to event listener over secure http
+channel.
Tested:
- - Created subscription with https destination
- url. Using SubmitTestEvent action set the
- event and can see event on event listener.
+ - Created subscription with https destination url. Using
+ SubmitTestEvent action set the event and can see event on event
+ listener.
- Validator passed.
Change-Id: I44c3918b39baa2eb5fddda9d635f99aa280a422a
Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
---
- http/http_client.hpp | 257 ++++++++++++------
+ http/http_client.hpp | 307 ++++++++++++------
.../include/event_service_manager.hpp | 2 +-
- 2 files changed, 176 insertions(+), 83 deletions(-)
+ 2 files changed, 202 insertions(+), 107 deletions(-)
diff --git a/http/http_client.hpp b/http/http_client.hpp
-index feabbba..aaf1b2d 100644
+index aad1cce..5e7ff47 100644
--- a/http/http_client.hpp
+++ b/http/http_client.hpp
@@ -20,6 +20,7 @@
@@ -33,8 +32,8 @@ index feabbba..aaf1b2d 100644
#include <boost/beast/version.hpp>
#include <include/async_resolve.hpp>
-@@ -44,6 +45,8 @@ enum class ConnState
- resolved,
+@@ -43,6 +44,8 @@ enum class ConnState
+ resolveFailed,
connectInProgress,
connectFailed,
+ handshakeInProgress,
@@ -42,7 +41,7 @@ index feabbba..aaf1b2d 100644
connected,
sendInProgress,
sendFailed,
-@@ -62,7 +65,9 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+@@ -61,7 +64,9 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
{
private:
crow::async_resolve::Resolver resolver;
@@ -52,8 +51,8 @@ index feabbba..aaf1b2d 100644
boost::asio::steady_timer timer;
boost::beast::flat_static_buffer<httpReadBodyLimit> buffer;
boost::beast::http::request<boost::beast::http::string_body> req;
-@@ -111,23 +116,52 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
- void doConnect()
+@@ -108,23 +113,52 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ const std::vector<boost::asio::ip::tcp::endpoint>& endpointList)
{
state = ConnState::connectInProgress;
+ sslConn.emplace(conn, ctx);
@@ -83,10 +82,10 @@ index feabbba..aaf1b2d 100644
+ };
conn.expires_after(std::chrono::seconds(30));
- conn.async_connect(
-- endPoints, [self(shared_from_this())](
-- const boost::beast::error_code ec,
-- const boost::asio::ip::tcp::endpoint& endpoint) {
-+ conn.async_connect(endPoints, std::move(respHandler));
+- endpointList, [self(shared_from_this())](
+- const boost::beast::error_code ec,
+- const boost::asio::ip::tcp::endpoint& endpoint) {
++ conn.async_connect(endpointList, std::move(respHandler));
+ }
+
+ void performHandshake()
@@ -113,7 +112,7 @@ index feabbba..aaf1b2d 100644
self->state = ConnState::connected;
self->handleConnState();
});
-@@ -135,106 +169,159 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+@@ -132,132 +166,187 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
void sendMessage(const std::string& data)
{
@@ -125,6 +124,19 @@ index feabbba..aaf1b2d 100644
req.body() = data;
req.prepare_payload();
+- // Set a timeout on the operation
+- conn.expires_after(std::chrono::seconds(30));
++ auto respHandler = [self(shared_from_this())](
++ const boost::beast::error_code ec,
++ const std::size_t& bytesTransferred) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR << "sendMessage() failed: " << ec.message();
++ self->state = ConnState::sendFailed;
++ self->handleConnState();
++ return;
++ }
+
- // Send the HTTP request to the remote host
- boost::beast::http::async_write(
- conn, req,
@@ -141,26 +153,15 @@ index feabbba..aaf1b2d 100644
- BMCWEB_LOG_DEBUG << "sendMessage() bytes transferred: "
- << bytesTransferred;
- boost::ignore_unused(bytesTransferred);
-+ auto respHandler = [self(shared_from_this())](
-+ const boost::beast::error_code ec,
-+ const std::size_t& bytesTransferred) {
-+ if (ec)
-+ {
-+ BMCWEB_LOG_ERROR << "sendMessage() failed: " << ec.message();
-+ self->state = ConnState::sendFailed;
-+ self->handleConnState();
-+ return;
-+ }
-
-- self->recvMessage();
-- });
-- }
+ BMCWEB_LOG_DEBUG << "sendMessage() bytes transferred: "
+ << bytesTransferred;
+ boost::ignore_unused(bytesTransferred);
+ self->recvMessage();
+ };
+- self->recvMessage();
+- });
++ // Set a timeout on the operation
+ conn.expires_after(std::chrono::seconds(30));
+ if (sslConn)
+ {
@@ -171,7 +172,8 @@ index feabbba..aaf1b2d 100644
+ {
+ boost::beast::http::async_write(conn, req, std::move(respHandler));
+ }
-+ }
+ }
+-
void recvMessage()
{
state = ConnState::recvInProgress;
@@ -191,6 +193,33 @@ index feabbba..aaf1b2d 100644
+ BMCWEB_LOG_DEBUG << "recvMessage() bytes transferred: "
+ << bytesTransferred;
+ boost::ignore_unused(bytesTransferred);
++
++ // Check if the response and header are received
++ if (!self->parser->is_done())
++ {
++ // The parser failed to receive the response
++ BMCWEB_LOG_ERROR
++ << "recvMessage() parser failed to receive response";
++ self->state = ConnState::recvFailed;
++ self->handleConnState();
++ return;
++ }
++
++ unsigned int respCode = self->parser->get().result_int();
++ BMCWEB_LOG_DEBUG << "recvMessage() Header Response Code: "
++ << respCode;
++
++ // 2XX response is considered to be successful
++ if ((respCode < 200) || (respCode >= 300))
++ {
++ // The listener failed to receive the Sent-Event
++ BMCWEB_LOG_ERROR << "recvMessage() Listener Failed to "
++ "receive Sent-Event";
++ self->state = ConnState::recvFailed;
++ self->handleConnState();
++ return;
++ }
++
+ // Send is successful, Lets remove data from queue
+ // check for next request data in queue.
+ if (!self->requestDataQueue.empty())
@@ -271,34 +300,56 @@ index feabbba..aaf1b2d 100644
- BMCWEB_LOG_DEBUG << "recvMessage() data: "
- << self->parser->get();
-
-- // Send is successful, Lets remove data from queue
-- // check for next request data in queue.
-- if (!self->requestDataQueue.empty())
+- // Check if the response and header are received
+- if (!self->parser->is_done())
+ else
{
-- self->requestDataQueue.pop_front();
+- // The parser failed to receive the response
+- BMCWEB_LOG_ERROR
+- << "recvMessage() parser failed to receive response";
+- self->state = ConnState::recvFailed;
+- self->handleConnState();
+- return;
+ BMCWEB_LOG_DEBUG << "Connection closed gracefully...";
}
-- self->state = ConnState::idle;
+ self->conn.close();
+- unsigned int respCode = self->parser->get().result_int();
+- BMCWEB_LOG_DEBUG << "recvMessage() Header Response Code: "
+- << respCode;
+-
+- // 2XX response is considered to be successful
+- if ((respCode < 200) || (respCode >= 300))
++ if ((self->state != ConnState::suspended) &&
++ (self->state != ConnState::terminated))
+ {
+- // The listener failed to receive the Sent-Event
+- BMCWEB_LOG_ERROR << "recvMessage() Listener Failed to "
+- "receive Sent-Event";
+- self->state = ConnState::recvFailed;
++ self->state = ConnState::closed;
+ self->handleConnState();
+- return;
+ }
+-
+- // Send is successful, Lets remove data from queue
+- // check for next request data in queue.
+- if (!self->requestDataQueue.empty())
+- {
+- self->requestDataQueue.pop_front();
+- }
+- self->state = ConnState::idle;
+-
- // Keep the connection alive if server supports it
- // Else close the connection
- BMCWEB_LOG_DEBUG << "recvMessage() keepalive : "
- << self->parser->keep_alive();
- if (!self->parser->keep_alive())
-+ if ((self->state != ConnState::suspended) &&
-+ (self->state != ConnState::terminated))
- {
+- {
- // Abort the connection since server is not keep-alive
- // enabled
- self->state = ConnState::abortConnection;
-+ self->state = ConnState::closed;
-+ self->handleConnState();
- }
--
-- // Returns ownership of the parsed message
-- self->parser->release();
+- }
-
- self->handleConnState();
});
@@ -345,7 +396,7 @@ index feabbba..aaf1b2d 100644
}
}
-@@ -301,6 +388,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+@@ -330,6 +419,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
{
case ConnState::resolveInProgress:
case ConnState::connectInProgress:
@@ -353,7 +404,7 @@ index feabbba..aaf1b2d 100644
case ConnState::sendInProgress:
case ConnState::recvInProgress:
case ConnState::closeInProgress:
-@@ -332,6 +420,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+@@ -356,6 +446,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
}
case ConnState::resolveFailed:
case ConnState::connectFailed:
@@ -361,7 +412,7 @@ index feabbba..aaf1b2d 100644
case ConnState::sendFailed:
case ConnState::recvFailed:
case ConnState::retry:
-@@ -370,7 +459,8 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+@@ -394,7 +485,8 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
public:
explicit HttpClient(boost::asio::io_context& ioc, const std::string& id,
const std::string& destIP, const std::string& destPort,
@@ -371,7 +422,7 @@ index feabbba..aaf1b2d 100644
conn(ioc),
timer(ioc), req(boost::beast::http::verb::post, destUri, 11),
state(ConnState::initialized), subId(id), host(destIP), port(destPort),
-@@ -383,8 +473,11 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+@@ -407,8 +499,11 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
req.keep_alive(true);
requestDataQueue.set_capacity(maxRequestQueueSize);
@@ -385,10 +436,10 @@ index feabbba..aaf1b2d 100644
{
if ((state == ConnState::suspended) || (state == ConnState::terminated))
diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
-index a8f7517..d4a5bc5 100644
+index 08d0b98..f1ce0c0 100644
--- a/redfish-core/include/event_service_manager.hpp
+++ b/redfish-core/include/event_service_manager.hpp
-@@ -397,7 +397,7 @@ class Subscription
+@@ -385,7 +385,7 @@ class Subscription : public persistent_data::UserSubscription
{
conn = std::make_shared<crow::HttpClient>(
crow::connections::systemBus->get_io_context(), id, host, port,
@@ -398,4 +449,5 @@ index a8f7517..d4a5bc5 100644
Subscription(const std::shared_ptr<boost::beast::tcp_stream>& adaptor) :
--
-2.25.1
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0004-Add-Server-Sent-Events-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0004-Add-Server-Sent-Events-support.patch
index da281467e..ea521a7e4 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0004-Add-Server-Sent-Events-support.patch
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0004-Add-Server-Sent-Events-support.patch
@@ -1,4 +1,4 @@
-From 54bdd897bd416fef4c043224b398b1b6d47fd271 Mon Sep 17 00:00:00 2001
+From d7a2660f200c38e74bfcbfe55b8da1b8bed08833 Mon Sep 17 00:00:00 2001
From: AppaRao Puli <apparao.puli@linux.intel.com>
Date: Fri, 12 Mar 2021 18:53:25 +0000
Subject: [PATCH] Add Server-Sent-Events support
@@ -21,47 +21,37 @@ Tested:
Change-Id: I36956565cbba30c2007852c9471f477f6d1736e9
Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+Signed-off-by: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com>
---
- http/http_connection.hpp | 14 +-
+ http/http_connection.hpp | 10 +-
http/http_response.hpp | 7 +-
http/routing.hpp | 71 ++++++++++
http/server_sent_event.hpp | 279 +++++++++++++++++++++++++++++++++++++
- 4 files changed, 365 insertions(+), 6 deletions(-)
+ 4 files changed, 362 insertions(+), 5 deletions(-)
create mode 100644 http/server_sent_event.hpp
diff --git a/http/http_connection.hpp b/http/http_connection.hpp
-index a1a7045..90535c5 100644
+index 8e53afa..a1bbfce 100644
--- a/http/http_connection.hpp
+++ b/http/http_connection.hpp
-@@ -331,7 +331,7 @@ class Connection :
- BMCWEB_LOG_INFO << "Request: "
- << " " << this << " HTTP/" << req->version() / 10 << "."
- << req->version() % 10 << ' ' << req->methodString()
-- << " " << req->target() << " " << req->ipAddress;
-+ << " " << req->url << " " << req->ipAddress;
+@@ -378,11 +378,13 @@ class Connection :
+ [self] { self->completeRequest(); });
+ });
- needToCallAfterHandlers = false;
-
-@@ -350,11 +350,15 @@ class Connection :
- boost::asio::post(self->adaptor.get_executor(),
- [self] { self->completeRequest(); });
- });
-- if (req->isUpgrade() &&
-- boost::iequals(
-- req->getHeaderValue(boost::beast::http::field::upgrade),
-- "websocket"))
-+
-+ if ((req->isUpgrade() &&
-+ boost::iequals(req->getHeaderValue(
-+ boost::beast::http::field::upgrade),
-+ "websocket")) ||
-+ (req->url == "/sse"))
- {
-+ BMCWEB_LOG_DEBUG << "Request: " << this
-+ << " is getting upgraded";
- handler->handleUpgrade(*req, res, std::move(adaptor));
- // delete lambda with self shared_ptr
- // to enable connection destruction
+- if (thisReq.isUpgrade() &&
+- boost::iequals(
+- thisReq.getHeaderValue(boost::beast::http::field::upgrade),
+- "websocket"))
++ if ((thisReq.isUpgrade() &&
++ boost::iequals(
++ thisReq.getHeaderValue(boost::beast::http::field::upgrade),
++ "websocket")) ||
++ (req->url == "/sse"))
+ {
++ BMCWEB_LOG_DEBUG << "Request: " << this << " is getting upgraded";
+ handler->handleUpgrade(thisReq, res, std::move(adaptor));
+ // delete lambda with self shared_ptr
+ // to enable connection destruction
diff --git a/http/http_response.hpp b/http/http_response.hpp
index a983d4a..07b0265 100644
--- a/http/http_response.hpp
@@ -93,7 +83,7 @@ index a983d4a..07b0265 100644
// In case of a JSON object, set the Content-Type header
void jsonMode()
diff --git a/http/routing.hpp b/http/routing.hpp
-index d2a10b2..25e4ce8 100644
+index 5d9c8e3..bfff107 100644
--- a/http/routing.hpp
+++ b/http/routing.hpp
@@ -6,6 +6,7 @@
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0005-Add-SSE-style-subscription-support-to-eventservice.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0005-Add-SSE-style-subscription-support-to-eventservice.patch
index 42a1ebbf0..ee69081ef 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0005-Add-SSE-style-subscription-support-to-eventservice.patch
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0005-Add-SSE-style-subscription-support-to-eventservice.patch
@@ -1,4 +1,4 @@
-From 36c1391749e19e4a25ca6e57d369457f48e6bb11 Mon Sep 17 00:00:00 2001
+From 799e47842e179f7c752712004f0e96d3219eee11 Mon Sep 17 00:00:00 2001
From: AppaRao Puli <apparao.puli@linux.intel.com>
Date: Tue, 16 Mar 2021 15:37:24 +0000
Subject: [PATCH] Add SSE style subscription support to eventservice
@@ -18,33 +18,33 @@ Tested:
response.
- Ran RedfishValidation and its passed.
-Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
-Signed-off-by: Nitin Wankhade <nitinx.arunrao.wankhade@intel.com>
Change-Id: I7f4b7a34974080739c4ba968ed570489af0474de
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+Signed-off-by: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com>
---
http/http_connection.hpp | 2 +-
include/eventservice_sse.hpp | 75 +++++
- .../include/event_service_manager.hpp | 111 +++++--
+ .../include/event_service_manager.hpp | 109 +++++--
redfish-core/include/server_sent_events.hpp | 290 ------------------
redfish-core/lib/event_service.hpp | 8 +-
src/webserver_main.cpp | 2 +
- 6 files changed, 165 insertions(+), 323 deletions(-)
+ 6 files changed, 164 insertions(+), 322 deletions(-)
create mode 100644 include/eventservice_sse.hpp
delete mode 100644 redfish-core/include/server_sent_events.hpp
diff --git a/http/http_connection.hpp b/http/http_connection.hpp
-index 90535c5..37c0a0b 100644
+index a1bbfce..2d08501 100644
--- a/http/http_connection.hpp
+++ b/http/http_connection.hpp
-@@ -355,7 +355,7 @@ class Connection :
- boost::iequals(req->getHeaderValue(
- boost::beast::http::field::upgrade),
- "websocket")) ||
-- (req->url == "/sse"))
-+ (req->url == "/redfish/v1/EventService/Subscriptions/SSE"))
- {
- BMCWEB_LOG_DEBUG << "Request: " << this
- << " is getting upgraded";
+@@ -382,7 +382,7 @@ class Connection :
+ boost::iequals(
+ thisReq.getHeaderValue(boost::beast::http::field::upgrade),
+ "websocket")) ||
+- (req->url == "/sse"))
++ (req->url == "/redfish/v1/EventService/Subscriptions/SSE"))
+ {
+ BMCWEB_LOG_DEBUG << "Request: " << this << " is getting upgraded";
+ handler->handleUpgrade(thisReq, res, std::move(adaptor));
diff --git a/include/eventservice_sse.hpp b/include/eventservice_sse.hpp
new file mode 100644
index 0000000..14daf00
@@ -127,7 +127,7 @@ index 0000000..14daf00
+} // namespace eventservice_sse
+} // namespace redfish
diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
-index ca46aa7..9397271 100644
+index 3f398d7..dd833ce 100644
--- a/redfish-core/include/event_service_manager.hpp
+++ b/redfish-core/include/event_service_manager.hpp
@@ -22,15 +22,17 @@
@@ -217,23 +217,23 @@ index ca46aa7..9397271 100644
~Subscription() = default;
-@@ -412,13 +412,14 @@ class Subscription : public persistent_data::UserSubscription
- }
- conn->addHeaders(reqHeaders);
- conn->sendData(msg);
-- this->eventSeqNum++;
- }
+@@ -417,7 +417,7 @@ class Subscription : public persistent_data::UserSubscription
if (sseConn != nullptr)
{
- sseConn->sendData(eventSeqNum, msg);
+ sseConn->sendEvent(std::to_string(eventSeqNum), msg);
}
-+
+ }
+
+@@ -508,6 +508,7 @@ class Subscription : public persistent_data::UserSubscription
+
+ this->sendEvent(
+ msg.dump(2, ' ', true, nlohmann::json::error_handler_t::replace));
+ this->eventSeqNum++;
}
+ #endif
- void sendTestEventLog()
@@ -578,14 +579,39 @@ class Subscription : public persistent_data::UserSubscription
return eventSeqNum;
}
@@ -622,7 +622,7 @@ index 7613d7b..0000000
-
-} // namespace crow
diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
-index 67ad014..f8a2dac 100644
+index 8609862..249e594 100644
--- a/redfish-core/lib/event_service.hpp
+++ b/redfish-core/lib/event_service.hpp
@@ -37,8 +37,6 @@ static constexpr const std::array<const char*, 1> supportedResourceTypes = {
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0006-Add-EventService-SSE-filter-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0006-Add-EventService-SSE-filter-support.patch
index 9043bd0b9..3914cc81a 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0006-Add-EventService-SSE-filter-support.patch
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0006-Add-EventService-SSE-filter-support.patch
@@ -1,4 +1,4 @@
-From 22c6b6cfb468f8de9ff3ea051dffdba05778645e Mon Sep 17 00:00:00 2001
+From 769f0e20d0a7e786d7091ffb7ee57d35204dfa28 Mon Sep 17 00:00:00 2001
From: AppaRao Puli <apparao.puli@linux.intel.com>
Date: Wed, 17 Mar 2021 01:16:50 +0000
Subject: [PATCH] Add EventService SSE filter support
@@ -41,7 +41,7 @@ Change-Id: I55c6f53bb5e57aa1f2d1601f1a16525a33b13bd2
5 files changed, 181 insertions(+), 9 deletions(-)
diff --git a/include/eventservice_sse.hpp b/include/eventservice_sse.hpp
-index 14daf00..2f22f98 100644
+index 14daf00..fed7fec 100644
--- a/include/eventservice_sse.hpp
+++ b/include/eventservice_sse.hpp
@@ -23,16 +23,153 @@ static bool createSubscription(std::shared_ptr<crow::SseConnection>& conn,
@@ -203,7 +203,7 @@ index 14daf00..2f22f98 100644
std::string id =
redfish::EventServiceManager::getInstance().addSubscription(subValue,
diff --git a/redfish-core/include/error_messages.hpp b/redfish-core/include/error_messages.hpp
-index 10567d1..f29e326 100644
+index 3d11cc4..90084e3 100644
--- a/redfish-core/include/error_messages.hpp
+++ b/redfish-core/include/error_messages.hpp
@@ -971,6 +971,15 @@ nlohmann::json mutualExclusiveProperties(const std::string& arg1,
@@ -223,10 +223,10 @@ index 10567d1..f29e326 100644
} // namespace redfish
diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
-index 5886d81..c3e7f61 100644
+index dd833ce..861f4cb 100644
--- a/redfish-core/include/event_service_manager.hpp
+++ b/redfish-core/include/event_service_manager.hpp
-@@ -56,6 +56,11 @@ static constexpr const char* eventServiceFile =
+@@ -55,6 +55,11 @@ static constexpr const char* eventServiceFile =
static constexpr const uint8_t maxNoOfSubscriptions = 20;
static constexpr const uint8_t maxNoOfSSESubscriptions = 10;
@@ -239,10 +239,10 @@ index 5886d81..c3e7f61 100644
static std::optional<boost::asio::posix::stream_descriptor> inotifyConn;
static constexpr const char* redfishEventLogDir = "/var/log";
diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
-index 2e7c3f3..9def549 100644
+index 249e594..6f01707 100644
--- a/redfish-core/lib/event_service.hpp
+++ b/redfish-core/lib/event_service.hpp
-@@ -25,11 +25,6 @@
+@@ -21,11 +21,6 @@
namespace redfish
{
@@ -255,10 +255,10 @@ index 2e7c3f3..9def549 100644
"TerminateAfterRetries", "SuspendRetries", "RetryForever"};
diff --git a/redfish-core/src/error_messages.cpp b/redfish-core/src/error_messages.cpp
-index 48edaf1..bebb6d8 100644
+index 9c28e8f..2394398 100644
--- a/redfish-core/src/error_messages.cpp
+++ b/redfish-core/src/error_messages.cpp
-@@ -2174,6 +2174,32 @@ void mutualExclusiveProperties(crow::Response& res, const std::string& arg1,
+@@ -2173,6 +2173,32 @@ void mutualExclusiveProperties(crow::Response& res, const std::string& arg1,
addMessageToErrorJson(res.jsonValue, mutualExclusiveProperties(arg1, arg2));
}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0010-Remove-Terminated-Event-Subscriptions.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0010-Remove-Terminated-Event-Subscriptions.patch
index 7fcc235d2..9af5a066b 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0010-Remove-Terminated-Event-Subscriptions.patch
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0010-Remove-Terminated-Event-Subscriptions.patch
@@ -1,6 +1,6 @@
-From adaa5cb4c494148430b90edb248260eb2e66bca7 Mon Sep 17 00:00:00 2001
-From: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com>
-Date: Wed, 8 Sep 2021 15:42:52 +0530
+From f665ba085bb2310f008b7534f827fb401ad973c2 Mon Sep 17 00:00:00 2001
+From: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
+Date: Tue, 12 Oct 2021 08:19:51 +0000
Subject: [PATCH] Delete/Remove Terminated Event Subscription(s)
Added functionality to delete/remove event subscription(s) which are
@@ -23,14 +23,14 @@ Change-Id: If447acb2db74fb29a5d1cfe6194b77cda82bc8a1
Signed-off-by: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com>
---
http/http_client.hpp | 43 +++++++++++++++----
- .../include/event_service_manager.hpp | 37 ++++++++++++++++
- 2 files changed, 71 insertions(+), 9 deletions(-)
+ .../include/event_service_manager.hpp | 36 ++++++++++++++++
+ 2 files changed, 70 insertions(+), 9 deletions(-)
diff --git a/http/http_client.hpp b/http/http_client.hpp
-index aaf1b2d..4f62c40 100644
+index 5e7ff47..54ae2c3 100644
--- a/http/http_client.hpp
+++ b/http/http_client.hpp
-@@ -56,6 +56,8 @@ enum class ConnState
+@@ -55,6 +55,8 @@ enum class ConnState
closeInProgress,
closed,
suspended,
@@ -39,7 +39,7 @@ index aaf1b2d..4f62c40 100644
terminated,
abortConnection,
retry
-@@ -263,7 +265,14 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+@@ -288,7 +290,14 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
}
void doClose()
{
@@ -55,7 +55,7 @@ index aaf1b2d..4f62c40 100644
// Set the timeout on the tcp stream socket for the async operation
conn.expires_after(std::chrono::seconds(30));
-@@ -293,8 +302,11 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+@@ -318,8 +327,11 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
}
self->conn.close();
@@ -69,7 +69,7 @@ index aaf1b2d..4f62c40 100644
{
self->state = ConnState::closed;
self->handleConnState();
-@@ -316,8 +328,11 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+@@ -341,8 +353,11 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
}
conn.close();
@@ -83,7 +83,7 @@ index aaf1b2d..4f62c40 100644
{
state = ConnState::closed;
handleConnState();
-@@ -340,8 +355,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+@@ -365,8 +380,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
BMCWEB_LOG_DEBUG << "Retry policy: " << retryPolicyAction;
if (retryPolicyAction == "TerminateAfterRetries")
{
@@ -93,7 +93,7 @@ index aaf1b2d..4f62c40 100644
}
if (retryPolicyAction == "SuspendRetries")
{
-@@ -392,6 +406,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+@@ -423,6 +437,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
case ConnState::sendInProgress:
case ConnState::recvInProgress:
case ConnState::closeInProgress:
@@ -101,7 +101,7 @@ index aaf1b2d..4f62c40 100644
{
BMCWEB_LOG_DEBUG << "Async operation is already in progress";
break;
-@@ -413,7 +428,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+@@ -439,7 +454,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
break;
}
case ConnState::suspended:
@@ -110,7 +110,7 @@ index aaf1b2d..4f62c40 100644
{
doClose();
break;
-@@ -480,7 +495,8 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+@@ -506,7 +521,8 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
}
void sendData(const std::string& data)
{
@@ -120,7 +120,7 @@ index aaf1b2d..4f62c40 100644
{
return;
}
-@@ -489,6 +505,15 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+@@ -524,6 +540,15 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
return;
}
@@ -137,7 +137,7 @@ index aaf1b2d..4f62c40 100644
const std::vector<std::pair<std::string, std::string>>& httpHeaders)
{
diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
-index 8d7067b..79618f6 100644
+index 6f60a31..363adb0 100644
--- a/redfish-core/include/event_service_manager.hpp
+++ b/redfish-core/include/event_service_manager.hpp
@@ -591,6 +591,14 @@ class Subscription : public persistent_data::UserSubscription
@@ -254,5 +254,5 @@ index 8d7067b..79618f6 100644
{
std::shared_ptr<Subscription> entry = it.second;
--
-2.17.1
+2.25.1
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0011-Fix-bmcweb-crash-while-deleting-terminated-subscriptions.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0011-Fix-bmcweb-crash-while-deleting-terminated-subscriptions.patch
new file mode 100644
index 000000000..585f7bf09
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0011-Fix-bmcweb-crash-while-deleting-terminated-subscriptions.patch
@@ -0,0 +1,141 @@
+From 5b87bb61b58e92a8c5af37a7959347747409a65c Mon Sep 17 00:00:00 2001
+From: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com>
+Date: Thu, 14 Oct 2021 02:56:11 +0530
+Subject: [PATCH] Fix bmcweb crash while deleting terminated subscriptions
+
+This commit fixes bmcweb crash while deleting the terminated
+subscriptions. In the earlier implementation, detection of subscription
+to be deleted and the deletion(erase) was happening in the same loop.
+Due to this, if the Subscription to be deleted is the last one in the
+list, the loop will enter into infinite loop. The fix is to keep the
+detection and deletion loop separate.
+Also, this commit adds code to :
+ - Delete from persistent storage
+ - Add journal entry for deleted entry
+ - update number of subcribers and update persistent storage.
+
+Apart from this, this commit also moves the retry timer check to the top
+to avoid multiple calls to close when the retry count is 3 and timer is
+running.
+
+Tested:
+ - Checked journal logs to confirm each retry is actually spanned to be
+ 30 secs
+ - Verified Journal entry for deleted subscription after retires.
+ - Verified Event service functionality by making three subscriptions:
+ retry for ever, terminate after retires and suspend after retries.
+
+Change-Id: I425a6c749923ce86c457a36394deb0fbbee232db
+Signed-off-by: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com>
+---
+ http/http_client.hpp | 11 ++--
+ .../include/event_service_manager.hpp | 59 ++++++++++++++++---
+ 2 files changed, 58 insertions(+), 12 deletions(-)
+
+diff --git a/http/http_client.hpp b/http/http_client.hpp
+index 54ae2c3..162cb09 100644
+--- a/http/http_client.hpp
++++ b/http/http_client.hpp
+@@ -367,6 +367,12 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+
+ void waitAndRetry()
+ {
++ if (runningTimer)
++ {
++ BMCWEB_LOG_DEBUG << "Retry timer is already running.";
++ return;
++ }
++
+ if (retryCount >= maxRetryAttempts)
+ {
+ BMCWEB_LOG_ERROR << "Maximum number of retries reached.";
+@@ -393,11 +399,6 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ return;
+ }
+
+- if (runningTimer)
+- {
+- BMCWEB_LOG_DEBUG << "Retry timer is already running.";
+- return;
+- }
+ runningTimer = true;
+
+ retryCount++;
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index 363adb0..7af7a4d 100644
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -857,18 +857,63 @@ class EventServiceManager
+
+ void deleteTerminatedSubcriptions()
+ {
+- boost::container::flat_map<std::string,
+- std::shared_ptr<Subscription>>::iterator it =
+- subscriptionsMap.begin();
+- while (it != subscriptionsMap.end())
++ BMCWEB_LOG_ERROR << "Map size Before Delete : "
++ << subscriptionsMap.size();
++
++ std::vector<std::string> deleteIds;
++
++ // Determine Subscription ID's to be deleted.
++ for (const auto& it : subscriptionsMap)
+ {
+- std::shared_ptr<Subscription> entry = it->second;
++ std::shared_ptr<Subscription> entry = it.second;
+ if (entry->isTerminated())
+ {
+- subscriptionsMap.erase(it);
++ deleteIds.emplace_back(it.first);
++ }
++ }
++
++ // Delete the Terminated Subcriptions
++ for (std::string& id : deleteIds)
++ {
++ auto map1 = subscriptionsMap.find(id);
++ if (map1 != subscriptionsMap.end())
++ {
++ subscriptionsMap.erase(map1);
++ auto map2 = persistent_data::EventServiceStore::getInstance()
++ .subscriptionsConfigMap.find(id);
++ if (map2 != persistent_data::EventServiceStore::getInstance()
++ .subscriptionsConfigMap.end())
++ {
++ persistent_data::EventServiceStore::getInstance()
++ .subscriptionsConfigMap.erase(map2);
++ }
++ else
++ {
++ BMCWEB_LOG_ERROR << "Couldn't find ID: " << id
++ << " in subscriptionsConfigMap";
++ }
++
++ /* Log event for subscription delete. */
++ sd_journal_send("MESSAGE=Event subscription removed.(Id = %s)",
++ id.c_str(), "PRIORITY=%i", LOG_INFO,
++ "REDFISH_MESSAGE_ID=%s",
++ "OpenBMC.0.1.EventSubscriptionRemoved",
++ "REDFISH_MESSAGE_ARGS=%s", id.c_str(), NULL);
++ }
++ else
++ {
++ BMCWEB_LOG_ERROR << "Couldn't find ID: " << id
++ << " in subscriptionsMap";
+ }
+- it++;
+ }
++ if (deleteIds.size())
++ {
++ updateNoOfSubscribersCount();
++ persistSubscriptionData();
++ }
++
++ BMCWEB_LOG_ERROR << "Map size After Delete : "
++ << subscriptionsMap.size();
+ }
+
+ void updateNoOfSubscribersCount()
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/README b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/README
index cd2e1c2bc..c09967456 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/README
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/README
@@ -3,26 +3,32 @@ the upstream patches. These will be remove as soon as
thee gets merged upstream.
Upstream revision information:
- - EventService : Fix retry handling for http-client
- https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/40731/21
+ - EventService : Add unmerged changes for http retry support (Downstream patch)
+ file://eventservice/0001-Add-unmerged-changes-for-http-retry-support.patch
- EventService: https client support
- https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/31735/40
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/31735/40 (Rebased on latest bmcweb)
- Add Server-Sent-Events support
- https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/41258/7
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/41258/9
- Add SSE style subscription support to eventservice
- https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/41319/8
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/41319/10
- Add EventService SSE filter support
- https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/41349/5
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/41349/7 (Modified boost::urls::query_params_view to boost::urls::url_view::params_type)
- - EventService Log events for subscription actions
- file://telemetry/0007-EventService-Log-events-for-subscription-actions.patch
+ - EventService Log events for subscription actions (Downstream patch)
+ file://eventservice/0007-EventService-Log-events-for-subscription-actions.patch
- - Add checks on Event-Subscription input parameters
- file://telemetry/0008-Add-checks-on-Event-Subscription-input-parameters.patch
+ - Add checks on Event-Subscription input parameters (Downstream patch)
+ file://eventservice//0008-Add-checks-on-Event-Subscription-input-parameters.patch
- Restructure Redifsh EventLog Transmit code flow
- file://telemetry/0009-Restructure-Redifsh-EventLog-Transmit-code-flow.patch
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/44449/3
+
+ - Remove Terminated Event Subscriptions (Downstream patch)
+ file://eventservice/0010-Remove-Terminated-Event-Subscriptions.patch
+
+ - Fix bmcweb crash while deleting terminated subscriptions (Downstream patch)
+ file://eventservice/0011-Fix-bmcweb-crash-while-deleting-terminated-subscriptions.patch