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.patch547
1 files changed, 0 insertions, 547 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
deleted file mode 100644
index 54f00aa39..000000000
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-EventService-https-client-support.patch
+++ /dev/null
@@ -1,547 +0,0 @@
-From d340953bc925ff8535c5a8fac54db24b243ba8ad Mon Sep 17 00:00:00 2001
-From: AppaRao Puli <apparao.puli@linux.intel.com>
-Date: Mon, 19 Oct 2020 13:21:42 +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>
-Signed-off-by: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com>
----
- http/http_client.hpp | 370 +++++++++++++-----
- .../include/event_service_manager.hpp | 2 +-
- 2 files changed, 267 insertions(+), 105 deletions(-)
-
-diff --git a/http/http_client.hpp b/http/http_client.hpp
-index 5c7b13f..d782dee 100644
---- a/http/http_client.hpp
-+++ b/http/http_client.hpp
-@@ -31,12 +31,17 @@ namespace crow
- {
-
- static constexpr uint8_t maxRequestQueueSize = 50;
-+static constexpr unsigned int httpReadBodyLimit = 1024;
-
- enum class ConnState
- {
- initialized,
-+ resolveInProgress,
-+ resolveFailed,
-+ resolved,
- connectInProgress,
- connectFailed,
-+ sslHandshakeInProgress,
- connected,
- sendInProgress,
- sendFailed,
-@@ -50,53 +55,124 @@ 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;
- boost::asio::steady_timer timer;
-- boost::beast::flat_buffer buffer;
-+ boost::beast::flat_static_buffer<httpReadBodyLimit> buffer;
-+ std::optional<
-+ boost::beast::http::response_parser<boost::beast::http::string_body>>
-+ parser;
- boost::beast::http::request<boost::beast::http::string_body> req;
-- boost::beast::http::response<boost::beast::http::string_body> res;
- boost::asio::ip::tcp::resolver::results_type endpoint;
-- std::vector<std::pair<std::string, std::string>> headers;
-+ boost::beast::http::fields fields;
- std::queue<std::string> requestDataQueue;
-- ConnState state;
- std::string subId;
- 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;
-+ 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 (state == ConnState::connectInProgress)
-+ if (useSsl)
-+ {
-+ sslConn.emplace(conn, ctx);
-+ }
-+
-+ if ((state == ConnState::connectInProgress) ||
-+ (state == ConnState::sslHandshakeInProgress))
- {
- return;
- }
- state = ConnState::connectInProgress;
-
- BMCWEB_LOG_DEBUG << "Trying to connect to: " << host << ":" << port;
-- // Set a timeout on the operation
-+
-+ 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->sslConn)
-+ {
-+ self->performHandshake();
-+ }
-+ else
-+ {
-+ self->state = ConnState::connected;
-+ self->checkQueue();
-+ }
-+ };
-+
- 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;
-+ conn.async_connect(endpoint, std::move(respHandler));
-+ }
-+
-+ void performHandshake()
-+ {
-+ if (state == ConnState::sslHandshakeInProgress)
-+ {
-+ return;
-+ }
-+ state = ConnState::sslHandshakeInProgress;
-+
-+ 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->doCloseAndCheckQueue(ConnState::connectFailed);
-+ return;
-+ }
-+ self->state = ConnState::connected;
-+ BMCWEB_LOG_DEBUG << "SSL Handshake successfull";
-
-- self->checkQueue();
-- });
-+ self->checkQueue();
-+ });
- }
-
- void sendMessage(const std::string& data)
-@@ -107,100 +183,170 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
- }
- state = ConnState::sendInProgress;
-
-- BMCWEB_LOG_DEBUG << __FUNCTION__ << "(): " << host << ":" << port;
-+ BMCWEB_LOG_DEBUG << 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 = {};
-+ for (const auto& field : fields)
- {
-- req.set(key, value);
-+ req.set(field.name_string(), field.value());
- }
- req.set(boost::beast::http::field::host, host);
-+ req.set(boost::beast::http::field::content_type, "text/plain");
-+
-+ req.version(static_cast<int>(11)); // HTTP 1.1
-+ req.target(uri);
-+ req.method(boost::beast::http::verb::post);
- req.keep_alive(true);
-
- 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->doCloseAndCheckQueue(ConnState::sendFailed);
-+ 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();
-- });
-+ conn.expires_after(std::chrono::seconds(30));
-+ if (sslConn)
-+ {
-+ 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) {
-+ 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->doCloseAndCheckQueue(ConnState::recvFailed);
-+ return;
-+ }
-+ BMCWEB_LOG_DEBUG << "recvMessage() bytes transferred: "
-+ << bytesTransferred;
-+ boost::ignore_unused(bytesTransferred);
-+
-+ // TODO: check for return status code and perform
-+ // retry if fails(Ex: 40x). Take action depending on
-+ // retry policy.
-+ BMCWEB_LOG_DEBUG << "recvMessage() data: "
-+ << self->parser->get().body();
-+
-+ // Send is successful, Lets remove data from queue
-+ // check for next request data in queue.
-+ self->requestDataQueue.pop();
-+
-+ // Transfer ownership of the response
-+ self->parser->release();
-+
-+ // TODO: Implement the keep-alive connections.
-+ // Most of the web servers close connection abruptly
-+ // and might be reason due to which its observed that
-+ // stream_truncated(Next read) or partial_message
-+ // errors. So for now, closing connection and re-open
-+ // for all cases.
-+ self->doCloseAndCheckQueue(ConnState::closed);
-+ };
-+
-+ parser.emplace(std::piecewise_construct, std::make_tuple());
-+ parser->body_limit(httpReadBodyLimit);
-+ // Since these are all push style eventing, we are not
-+ // bothered about response parsing.
-+ parser->skip(true);
-+ buffer.consume(buffer.size());
-+
-+ conn.expires_after(std::chrono::seconds(30));
-+ if (sslConn)
-+ {
-+ boost::beast::http::async_read(*sslConn, buffer, *parser,
-+ std::move(respHandler));
-+ }
-+ else
-+ {
-+ boost::beast::http::async_read(conn, buffer, *parser,
-+ std::move(respHandler));
-+ }
-+ }
-+
-+ void doCloseAndCheckQueue(const ConnState setState = ConnState::closed)
-+ {
-+ if (sslConn)
-+ {
-+ conn.expires_after(std::chrono::seconds(30));
-+ sslConn->async_shutdown([self = shared_from_this(),
-+ setState{std::move(setState)}](
-+ const boost::system::error_code ec) {
- if (ec)
- {
-- BMCWEB_LOG_ERROR << "recvMessage() failed: "
-- << ec.message();
-- self->state = ConnState::recvFailed;
-- self->checkQueue();
-- 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_ERROR
-+ << "doCloseAndCheckQueue(): Connection "
-+ "closed by server. ";
-+ }
-+ else
-+ {
-+ BMCWEB_LOG_ERROR << "doCloseAndCheckQueue() failed: "
-+ << ec.message();
-+ }
- }
-- 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;
--
-- // Send is successful, Lets remove data from queue
-- // check for next request data in queue.
-- self->requestDataQueue.pop();
-- self->state = ConnState::idle;
-+ else
-+ {
-+ BMCWEB_LOG_DEBUG << "Connection closed gracefully...";
-+ }
-+ self->conn.cancel();
-+ self->state = setState;
- self->checkQueue();
- });
-- }
--
-- void doClose()
-- {
-- boost::beast::error_code ec;
-- conn.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)
-+ }
-+ else
- {
-- BMCWEB_LOG_ERROR << "shutdown failed: " << ec.message();
-- return;
-+ boost::beast::error_code ec;
-+ conn.expires_after(std::chrono::seconds(30));
-+ conn.socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both,
-+ ec);
-+ if (ec)
-+ {
-+ BMCWEB_LOG_ERROR << "doCloseAndCheckQueue() failed: "
-+ << ec.message();
-+ }
-+ else
-+ {
-+ BMCWEB_LOG_DEBUG << "Connection closed gracefully...";
-+ }
-+
-+ conn.close();
-+ state = setState;
-+ checkQueue();
- }
-- BMCWEB_LOG_DEBUG << "Connection closed gracefully";
-+ 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;
- }
-@@ -232,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))
- {
-@@ -256,14 +403,18 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
- << " seconds. RetryCount = " << retryCount;
- timer.expires_after(std::chrono::seconds(retryIntervalSecs));
- timer.async_wait(
-- [self = shared_from_this()](const boost::system::error_code&) {
-+ [self = shared_from_this()](boost::system::error_code) {
- self->runningTimer = false;
- self->connStateCheck();
- });
- return;
- }
-- // reset retry count.
-- retryCount = 0;
-+
-+ if (state == ConnState::idle)
-+ {
-+ // State idle means, previous attempt is successful.
-+ retryCount = 0;
-+ }
- connStateCheck();
-
- return;
-@@ -273,15 +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:
- {
-@@ -297,22 +454,22 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
- sendMessage(data);
- break;
- }
-+ default:
-+ break;
- }
- }
-
- 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),
-- timer(ioc), subId(id), host(destIP), port(destPort), uri(destUri),
-- retryCount(0), maxRetryAttempts(5), retryIntervalSecs(0),
-- retryPolicyAction("TerminateAfterRetries"), runningTimer(false)
-- {
-- boost::asio::ip::tcp::resolver resolver(ioc);
-- endpoint = resolver.resolve(host, port);
-- state = ConnState::initialized;
-- }
-+ const std::string& destUri,
-+ const bool inUseSsl = true) :
-+ 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)
-+ {}
-
- void sendData(const std::string& data)
- {
-@@ -337,7 +494,12 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
- void setHeaders(
- const std::vector<std::pair<std::string, std::string>>& httpHeaders)
- {
-- headers = httpHeaders;
-+ // Set headers
-+ for (const auto& [key, value] : httpHeaders)
-+ {
-+ // TODO: Validate the header fileds before assign.
-+ fields.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 54dafb4..f68ae1d 100644
---- a/redfish-core/include/event_service_manager.hpp
-+++ b/redfish-core/include/event_service_manager.hpp
-@@ -387,7 +387,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<boost::beast::tcp_stream>& adaptor) :
---
-2.17.1
-