summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-EventService-https-client-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-EventService-https-client-support.patch')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-EventService-https-client-support.patch405
1 files changed, 405 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-EventService-https-client-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-EventService-https-client-support.patch
new file mode 100644
index 000000000..274dd044a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-EventService-https-client-support.patch
@@ -0,0 +1,405 @@
+From f388587781c3d874b13b50ad39e8674f0bc08049 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Mon, 25 May 2020 16:14:39 +0530
+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.
+
+Tested:
+ - 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 | 270 +++++++++++++++++--------
+ redfish-core/include/event_service_manager.hpp | 2 +-
+ 2 files changed, 186 insertions(+), 86 deletions(-)
+
+diff --git a/http/http_client.hpp b/http/http_client.hpp
+index e6a7db1..27d2af3 100644
+--- a/http/http_client.hpp
++++ b/http/http_client.hpp
+@@ -17,6 +17,7 @@
+ #include <boost/asio/strand.hpp>
+ #include <boost/beast/core.hpp>
+ #include <boost/beast/http.hpp>
++#include <boost/beast/ssl.hpp>
+ #include <boost/beast/version.hpp>
+
+ #include <cstdlib>
+@@ -49,7 +50,10 @@ enum class ConnState
+ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ {
+ private:
+- boost::beast::tcp_stream conn;
++ boost::asio::io_context& ioc;
++ boost::asio::ssl::context ctx{boost::asio::ssl::context::tlsv12_client};
++ std::shared_ptr<boost::beast::ssl_stream<boost::beast::tcp_stream>> sslConn;
++ std::shared_ptr<boost::beast::tcp_stream> conn;
+ boost::asio::steady_timer timer;
+ boost::beast::flat_buffer buffer;
+ boost::beast::http::request<boost::beast::http::string_body> req;
+@@ -62,14 +66,37 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ std::string host;
+ std::string port;
+ std::string uri;
++ bool useSsl;
+ uint32_t retryCount;
+ uint32_t maxRetryAttempts;
+ uint32_t retryIntervalSecs;
+ std::string retryPolicyAction;
+ bool runningTimer;
+
++ inline boost::beast::tcp_stream& getConn()
++ {
++ if (useSsl)
++ {
++ return (boost::beast::get_lowest_layer(*sslConn));
++ }
++ else
++ {
++ return (*conn);
++ }
++ }
++
+ void doConnect()
+ {
++ if (useSsl)
++ {
++ sslConn = std::make_shared<
++ boost::beast::ssl_stream<boost::beast::tcp_stream>>(ioc, ctx);
++ }
++ else
++ {
++ conn = std::make_shared<boost::beast::tcp_stream>(ioc);
++ }
++
+ if (state == ConnState::connectInProgress)
+ {
+ return;
+@@ -77,25 +104,53 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ state = ConnState::connectInProgress;
+
+ BMCWEB_LOG_DEBUG << "Trying to connect to: " << host << ":" << port;
+- // Set a timeout on the operation
+- conn.expires_after(std::chrono::seconds(30));
+- conn.async_connect(endpoint, [self(shared_from_this())](
+- const boost::beast::error_code& ec,
+- const boost::asio::ip::tcp::resolver::
+- results_type::endpoint_type& ep) {
+- if (ec)
+- {
+- BMCWEB_LOG_ERROR << "Connect " << ep
+- << " failed: " << ec.message();
+- self->state = ConnState::connectFailed;
+- self->checkQueue();
+- return;
+- }
+- self->state = ConnState::connected;
+- BMCWEB_LOG_DEBUG << "Connected to: " << ep;
+
+- self->checkQueue();
+- });
++ auto respHandler =
++ [self(shared_from_this())](const boost::beast::error_code& ec,
++ const boost::asio::ip::tcp::resolver::
++ results_type::endpoint_type& ep) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR << "Connect " << ep
++ << " failed: " << ec.message();
++ self->state = ConnState::connectFailed;
++ self->checkQueue();
++ return;
++ }
++ BMCWEB_LOG_DEBUG << "Connected to: " << ep;
++ if (self->useSsl)
++ {
++ self->performHandshake();
++ }
++ else
++ {
++ self->state = ConnState::connected;
++ self->checkQueue();
++ }
++ };
++
++ getConn().expires_after(std::chrono::seconds(30));
++ getConn().async_connect(endpoint, std::move(respHandler));
++ }
++
++ void performHandshake()
++ {
++ sslConn->async_handshake(
++ boost::asio::ssl::stream_base::client,
++ [self(shared_from_this())](const boost::beast::error_code& ec) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR << "SSL handshake failed: "
++ << ec.message();
++ self->state = ConnState::connectFailed;
++ self->doCloseAndCheckQueue();
++ return;
++ }
++ self->state = ConnState::connected;
++ BMCWEB_LOG_DEBUG << "SSL Handshake successfull \n";
++
++ self->checkQueue();
++ });
+ }
+
+ void sendMessage(const std::string& data)
+@@ -108,7 +163,10 @@ 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 = {};
++ res = {};
++
++ req.version(11); // HTTP 1.1
+ req.target(uri);
+ req.method(boost::beast::http::verb::post);
+
+@@ -123,83 +181,121 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ 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->doCloseAndCheckQueue();
++ return;
++ }
++ BMCWEB_LOG_DEBUG << "sendMessage() bytes transferred: "
++ << bytesTransferred;
++ boost::ignore_unused(bytesTransferred);
+
+- // Send the HTTP request to the remote host
+- boost::beast::http::async_write(
+- conn, req,
+- [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->checkQueue();
+- return;
+- }
+- BMCWEB_LOG_DEBUG << "sendMessage() bytes transferred: "
+- << bytesTransferred;
+- boost::ignore_unused(bytesTransferred);
++ self->recvMessage();
++ };
+
+- self->recvMessage();
+- });
++ getConn().expires_after(std::chrono::seconds(30));
++ if (useSsl)
++ {
++ boost::beast::http::async_write(*sslConn, req,
++ std::move(respHandler));
++ }
++ else
++ {
++ boost::beast::http::async_write(*conn, req, std::move(respHandler));
++ }
+ }
+
+ void recvMessage()
+ {
+- // Receive the HTTP response
+- boost::beast::http::async_read(
+- conn, buffer, res,
+- [self(shared_from_this())](const boost::beast::error_code& ec,
+- const std::size_t& bytesTransferred) {
+- if (ec)
+- {
+- BMCWEB_LOG_ERROR << "recvMessage() failed: "
+- << ec.message();
+- self->state = ConnState::recvFailed;
+- self->checkQueue();
+- return;
+- }
+- BMCWEB_LOG_DEBUG << "recvMessage() 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 && ec != boost::beast::http::error::partial_message)
++ {
++ BMCWEB_LOG_ERROR << "recvMessage() failed: " << ec.message();
++ self->state = ConnState::recvFailed;
++ self->doCloseAndCheckQueue();
++ 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;
++ // Discard received data. We are not interested.
++ BMCWEB_LOG_DEBUG << "recvMessage() data: " << self->res;
+
+- // Send is successful, Lets remove data from queue
+- // check for next request data in queue.
+- self->requestDataQueue.pop();
+- self->state = ConnState::idle;
+- self->checkQueue();
+- });
++ // Send is successful, Lets remove data from queue
++ // check for next request data in queue.
++ self->requestDataQueue.pop();
++ self->state = ConnState::idle;
++
++ if (ec == boost::beast::http::error::partial_message)
++ {
++ // Least bothered about recv message. Partial
++ // message means, already data is sent. Lets close
++ // connection and let next request open connection
++ // to avoid truncated stream.
++ self->state = ConnState::closed;
++ self->doCloseAndCheckQueue();
++ return;
++ }
++
++ self->checkQueue();
++ };
++
++ getConn().expires_after(std::chrono::seconds(30));
++ if (useSsl)
++ {
++ boost::beast::http::async_read(*sslConn, buffer, res,
++ std::move(respHandler));
++ }
++ else
++ {
++ boost::beast::http::async_read(*conn, buffer, res,
++ std::move(respHandler));
++ }
+ }
+
+- void doClose()
++ void doCloseAndCheckQueue()
+ {
+ boost::beast::error_code ec;
+- conn.socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
++ getConn().cancel();
++ getConn().expires_after(std::chrono::seconds(30));
++ getConn().socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both,
++ ec);
+
+- state = ConnState::closed;
+- // not_connected happens sometimes so don't bother reporting it.
+- if (ec && ec != boost::beast::errc::not_connected)
++ if (ec && ec != boost::asio::error::eof)
+ {
+- BMCWEB_LOG_ERROR << "shutdown failed: " << ec.message();
+- return;
++ // Many https server closes connection abruptly
++ // i.e witnout close_notify. More details are at
++ // https://github.com/boostorg/beast/issues/824
++ if (ec == boost::asio::ssl::error::stream_truncated)
++ {
++ BMCWEB_LOG_DEBUG
++ << "doCloseAndCheckQueue(): Connection closed by server.";
++ }
++ else
++ {
++ BMCWEB_LOG_ERROR << "doCloseAndCheckQueue() failed: "
++ << ec.message();
++ }
+ }
++
++ getConn().close();
+ BMCWEB_LOG_DEBUG << "Connection closed gracefully";
++ checkQueue();
++ return;
+ }
+
+ void checkQueue(const bool newRecord = false)
+ {
+ if (requestDataQueue.empty())
+ {
+- // TODO: Having issue in keeping connection alive. So lets close if
+- // nothing to be transferred.
+- doClose();
+-
+ BMCWEB_LOG_DEBUG << "requestDataQueue is empty\n";
+ return;
+ }
+@@ -257,17 +353,20 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ 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) {
+- self->runningTimer = false;
+- self->connStateCheck();
+- });
++ timer.async_wait(
++ [self = shared_from_this()](boost::system::error_code) {
++ self->runningTimer = false;
++ self->connStateCheck();
++ });
+ return;
+ }
+ else
+ {
+- // reset retry count.
+- retryCount = 0;
++ if (state == ConnState::idle)
++ {
++ // State idle means, previous attempt is successful.
++ retryCount = 0;
++ }
+ }
+ connStateCheck();
+
+@@ -310,10 +409,11 @@ 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,
+- const std::string& destUri) :
+- conn(ioc),
++ const std::string& destUri,
++ const bool inUseSsl = true) :
++ ioc(ioc),
+ timer(ioc), subId(id), host(destIP), port(destPort), uri(destUri),
+- retryCount(0), maxRetryAttempts(5),
++ useSsl(inUseSsl), retryCount(0), maxRetryAttempts(5),
+ retryPolicyAction("TerminateAfterRetries"), runningTimer(false)
+ {
+ boost::asio::ip::tcp::resolver resolver(ioc);
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index 6362112..3ab2605 100644
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -383,7 +383,7 @@ class Subscription
+ {
+ conn = std::make_shared<crow::HttpClient>(
+ crow::connections::systemBus->get_io_context(), id, host, port,
+- path);
++ path, (uriProto == "https" ? true : false));
+ }
+
+ Subscription(const std::shared_ptr<crow::Request::Adaptor>& adaptor) :
+--
+2.7.4
+