summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEd Tanous <edtanous@google.com>2022-06-28 22:12:03 +0300
committerEd Tanous <edtanous@google.com>2023-05-30 23:56:15 +0300
commitf8ca6d79390b7f7fac5dbb82635dd6384810c668 (patch)
treeff1c55362a74f5a43d1c05d5d3924ab4d255f948
parent86a5ac983f9715f7b1a0f8dee355906ac648e1d3 (diff)
downloadbmcweb-f8ca6d79390b7f7fac5dbb82635dd6384810c668.tar.xz
Allow async resolver to be optional
This commit adds a meson option to allow selecting which dns resolver bmcweb uses. There are use cases, like Open Compute Project Inband Management Agent, that would require not using dbus, which would require us to fall back to the asio resolver. This commit makes the existing asio resolver constructor, and async_resolve methods match the equivalents in asio (which we intended to do anyway), then adds a macro and configure option for being able to select which resolver backend to rely on. Tested: Code can now compile without sdbusplus. Signed-off-by: Ed Tanous <edtanous@google.com> Change-Id: I3220214367179f131a60082bdfaf7e725d35c125
-rw-r--r--http/app.hpp5
-rw-r--r--http/http_client.hpp32
-rw-r--r--include/async_resolve.hpp40
-rw-r--r--meson.build4
-rw-r--r--meson_options.txt11
-rw-r--r--redfish-core/include/event_service_manager.hpp33
-rw-r--r--redfish-core/include/redfish_aggregator.hpp16
-rw-r--r--redfish-core/lib/event_service.hpp4
-rw-r--r--src/webserver_main.cpp4
9 files changed, 99 insertions, 50 deletions
diff --git a/http/app.hpp b/http/app.hpp
index a3a6e16255..d3cf48c1b1 100644
--- a/http/app.hpp
+++ b/http/app.hpp
@@ -183,6 +183,11 @@ class App
}
#endif
+ boost::asio::io_context& ioContext()
+ {
+ return *io;
+ }
+
private:
std::shared_ptr<boost::asio::io_context> io;
#ifdef BMCWEB_ENABLE_SSL
diff --git a/http/http_client.hpp b/http/http_client.hpp
index 2b498b7fb8..7a98b54497 100644
--- a/http/http_client.hpp
+++ b/http/http_client.hpp
@@ -146,7 +146,14 @@ class ConnectionInfo : public std::enable_shared_from_this<ConnectionInfo>
// Ascync callables
std::function<void(bool, uint32_t, Response&)> callback;
- crow::async_resolve::Resolver resolver;
+
+#ifdef BMCWEB_DBUS_DNS_RESOLVER
+ using Resolver = crow::async_resolve::Resolver;
+#else
+ using Resolver = boost::asio::ip::tcp::resolver;
+#endif
+ Resolver resolver;
+
boost::asio::ip::tcp::socket conn;
std::optional<boost::beast::ssl_stream<boost::asio::ip::tcp::socket&>>
sslConn;
@@ -162,15 +169,14 @@ class ConnectionInfo : public std::enable_shared_from_this<ConnectionInfo>
<< std::to_string(port)
<< ", id: " << std::to_string(connId);
- resolver.asyncResolve(host, port,
- std::bind_front(&ConnectionInfo::afterResolve,
- this, shared_from_this()));
+ resolver.async_resolve(host, std::to_string(port),
+ std::bind_front(&ConnectionInfo::afterResolve,
+ this, shared_from_this()));
}
- void afterResolve(
- const std::shared_ptr<ConnectionInfo>& /*self*/,
- const boost::beast::error_code& ec,
- const std::vector<boost::asio::ip::tcp::endpoint>& endpointList)
+ void afterResolve(const std::shared_ptr<ConnectionInfo>& /*self*/,
+ const boost::system::error_code& ec,
+ const Resolver::results_type& endpointList)
{
if (ec || (endpointList.empty()))
{
@@ -591,7 +597,7 @@ class ConnectionInfo : public std::enable_shared_from_this<ConnectionInfo>
unsigned int connIdIn) :
subId(idIn),
connPolicy(connPolicyIn), host(destIPIn), port(destPortIn),
- connId(connIdIn), conn(iocIn), timer(iocIn)
+ connId(connIdIn), resolver(iocIn), conn(iocIn), timer(iocIn)
{
if (useSSL)
{
@@ -833,8 +839,7 @@ class HttpClient
private:
std::unordered_map<std::string, std::shared_ptr<ConnectionPool>>
connectionPools;
- boost::asio::io_context& ioc =
- crow::connections::systemBus->get_io_context();
+ boost::asio::io_context& ioc;
std::shared_ptr<ConnectionPolicy> connPolicy;
// Used as a dummy callback by sendData() in order to call
@@ -847,9 +852,12 @@ class HttpClient
public:
HttpClient() = delete;
- explicit HttpClient(const std::shared_ptr<ConnectionPolicy>& connPolicyIn) :
+ explicit HttpClient(boost::asio::io_context& iocIn,
+ const std::shared_ptr<ConnectionPolicy>& connPolicyIn) :
+ ioc(iocIn),
connPolicy(connPolicyIn)
{}
+
HttpClient(const HttpClient&) = delete;
HttpClient& operator=(const HttpClient&) = delete;
HttpClient(HttpClient&&) = delete;
diff --git a/include/async_resolve.hpp b/include/async_resolve.hpp
index f44be4b73f..5e526cabc5 100644
--- a/include/async_resolve.hpp
+++ b/include/async_resolve.hpp
@@ -1,4 +1,5 @@
#pragma once
+#ifdef BMCWEB_DBUS_DNS_RESOLVER
#include "dbus_singleton.hpp"
#include "logging.hpp"
@@ -20,7 +21,9 @@ namespace async_resolve
class Resolver
{
public:
- Resolver() = default;
+ // unused io param used to keep interface identical to
+ // boost::asio::tcp:::resolver
+ explicit Resolver(boost::asio::io_context& /*io*/) {}
~Resolver() = default;
@@ -29,19 +32,37 @@ class Resolver
Resolver& operator=(const Resolver&) = delete;
Resolver& operator=(Resolver&&) = delete;
+ using results_type = std::vector<boost::asio::ip::tcp::endpoint>;
+
template <typename ResolveHandler>
- void asyncResolve(const std::string& host, uint16_t port,
- ResolveHandler&& handler)
+ // This function is kept using snake case so that it is interoperable with
+ // boost::asio::ip::tcp::resolver
+ // NOLINTNEXTLINE(readability-identifier-naming)
+ void async_resolve(const std::string& host, std::string_view port,
+ ResolveHandler&& handler)
{
BMCWEB_LOG_DEBUG << "Trying to resolve: " << host << ":" << port;
+
+ uint16_t portNum = 0;
+
+ auto it = std::from_chars(&*port.begin(), &*port.end(), portNum);
+ if (it.ec != std::errc())
+ {
+ BMCWEB_LOG_ERROR << "Failed to get the Port";
+ handler(std::make_error_code(std::errc::invalid_argument),
+ results_type{});
+
+ return;
+ }
+
uint64_t flag = 0;
crow::connections::systemBus->async_method_call(
- [host, port, handler{std::forward<ResolveHandler>(handler)}](
+ [host, portNum, handler{std::forward<ResolveHandler>(handler)}](
const boost::system::error_code& ec,
const std::vector<
std::tuple<int32_t, int32_t, std::vector<uint8_t>>>& resp,
const std::string& hostName, const uint64_t flagNum) {
- std::vector<boost::asio::ip::tcp::endpoint> endpointList;
+ results_type endpointList;
if (ec)
{
BMCWEB_LOG_ERROR << "Resolve failed: " << ec.message();
@@ -51,9 +72,11 @@ class Resolver
BMCWEB_LOG_DEBUG << "ResolveHostname returned: " << hostName << ":"
<< flagNum;
// Extract the IP address from the response
- for (auto resolveList : resp)
+ for (const std::tuple<int32_t, int32_t, std::vector<uint8_t>>&
+ resolveList : resp)
{
- std::vector<uint8_t> ipAddress = std::get<2>(resolveList);
+ const std::vector<uint8_t>& ipAddress =
+ std::get<2>(resolveList);
boost::asio::ip::tcp::endpoint endpoint;
if (ipAddress.size() == 4) // ipv4 address
{
@@ -81,7 +104,7 @@ class Resolver
handler(ec, endpointList);
return;
}
- endpoint.port(port);
+ endpoint.port(portNum);
BMCWEB_LOG_DEBUG << "resolved endpoint is : " << endpoint;
endpointList.push_back(endpoint);
}
@@ -96,3 +119,4 @@ class Resolver
} // namespace async_resolve
} // namespace crow
+#endif
diff --git a/meson.build b/meson.build
index 05e5e2effa..46d6e03557 100644
--- a/meson.build
+++ b/meson.build
@@ -41,6 +41,10 @@ if(get_option('buildtype') == 'minsize')
add_project_arguments('-DNDEBUG', language : 'cpp')
endif
+if(get_option('dns-resolver') == 'systemd-dbus')
+ add_project_arguments('-DBMCWEB_DBUS_DNS_RESOLVER', language : 'cpp')
+endif
+
# Disable lto when compiling with no optimization
if(get_option('optimization') == '0')
add_project_arguments('-fno-lto', language: 'cpp')
diff --git a/meson_options.txt b/meson_options.txt
index 8a440f98c9..3c2d3f78dd 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -236,6 +236,17 @@ option(
)
option(
+ 'dns-resolver',
+ type: 'combo',
+ choices: ['systemd-dbus', 'asio'],
+ value: 'systemd-dbus',
+ description: '''Sets which DNS resolver backend should be used.
+ systemd-dbus uses the Systemd ResolveHostname on dbus, but requires dbus
+ support. asio relies on boost::asio::tcp::resolver, but cannot resolve
+ names when boost threading is disabled.'''
+)
+
+option(
'redfish-aggregation',
type: 'feature',
value: 'disabled',
diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
index 6c2a569112..7ae47dd224 100644
--- a/redfish-core/include/event_service_manager.hpp
+++ b/redfish-core/include/event_service_manager.hpp
@@ -378,22 +378,16 @@ class Subscription : public persistent_data::UserSubscription
Subscription& operator=(Subscription&&) = delete;
Subscription(const std::string& inHost, uint16_t inPort,
- const std::string& inPath, const std::string& inUriProto) :
+ const std::string& inPath, const std::string& inUriProto,
+ boost::asio::io_context& ioc) :
host(inHost),
port(inPort), policy(std::make_shared<crow::ConnectionPolicy>()),
- client(policy), path(inPath), uriProto(inUriProto)
+ client(ioc, policy), path(inPath), uriProto(inUriProto)
{
// Subscription constructor
policy->invalidResp = retryRespHandler;
}
- explicit Subscription(
- const std::shared_ptr<boost::asio::ip::tcp::socket>& adaptor) :
- policy(std::make_shared<crow::ConnectionPolicy>()),
- client(policy),
- sseConn(std::make_shared<crow::ServerSentEvents>(adaptor))
- {}
-
~Subscription() = default;
bool sendEvent(std::string& msg)
@@ -602,12 +596,6 @@ class EventServiceManager
uint32_t retryAttempts = 0;
uint32_t retryTimeoutInterval = 0;
- EventServiceManager()
- {
- // Load config from persist store.
- initConfig();
- }
-
std::streampos redfishLogFilePosition{0};
size_t noOfEventLogSubscribers{0};
size_t noOfMetricReportSubscribers{0};
@@ -617,6 +605,8 @@ class EventServiceManager
uint64_t eventId{1};
+ boost::asio::io_context& ioc;
+
public:
EventServiceManager(const EventServiceManager&) = delete;
EventServiceManager& operator=(const EventServiceManager&) = delete;
@@ -624,9 +614,16 @@ class EventServiceManager
EventServiceManager& operator=(EventServiceManager&&) = delete;
~EventServiceManager() = default;
- static EventServiceManager& getInstance()
+ explicit EventServiceManager(boost::asio::io_context& iocIn) : ioc(iocIn)
+ {
+ // Load config from persist store.
+ initConfig();
+ }
+
+ static EventServiceManager&
+ getInstance(boost::asio::io_context* ioc = nullptr)
{
- static EventServiceManager handler;
+ static EventServiceManager handler(*ioc);
return handler;
}
@@ -662,7 +659,7 @@ class EventServiceManager
continue;
}
std::shared_ptr<Subscription> subValue =
- std::make_shared<Subscription>(host, port, path, urlProto);
+ std::make_shared<Subscription>(host, port, path, urlProto, ioc);
subValue->id = newSub->id;
subValue->destinationUrl = newSub->destinationUrl;
diff --git a/redfish-core/include/redfish_aggregator.hpp b/redfish-core/include/redfish_aggregator.hpp
index 1c514ecced..040733307d 100644
--- a/redfish-core/include/redfish_aggregator.hpp
+++ b/redfish-core/include/redfish_aggregator.hpp
@@ -374,12 +374,6 @@ class RedfishAggregator
private:
crow::HttpClient client;
- RedfishAggregator() :
- client(std::make_shared<crow::ConnectionPolicy>(getAggregationPolicy()))
- {
- getSatelliteConfigs(constructorCallback);
- }
-
// Dummy callback used by the Constructor so that it can report the number
// of satellite configs when the class is first created
static void constructorCallback(
@@ -735,15 +729,21 @@ class RedfishAggregator
}
public:
+ explicit RedfishAggregator(boost::asio::io_context& ioc) :
+ client(ioc,
+ std::make_shared<crow::ConnectionPolicy>(getAggregationPolicy()))
+ {
+ getSatelliteConfigs(constructorCallback);
+ }
RedfishAggregator(const RedfishAggregator&) = delete;
RedfishAggregator& operator=(const RedfishAggregator&) = delete;
RedfishAggregator(RedfishAggregator&&) = delete;
RedfishAggregator& operator=(RedfishAggregator&&) = delete;
~RedfishAggregator() = default;
- static RedfishAggregator& getInstance()
+ static RedfishAggregator& getInstance(boost::asio::io_context* io = nullptr)
{
- static RedfishAggregator handler;
+ static RedfishAggregator handler(*io);
return handler;
}
diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
index f74f215341..5f57ff761a 100644
--- a/redfish-core/lib/event_service.hpp
+++ b/redfish-core/lib/event_service.hpp
@@ -281,8 +281,8 @@ inline void requestRoutesEventDestinationCollection(App& app)
{
path = "/";
}
- std::shared_ptr<Subscription> subValue =
- std::make_shared<Subscription>(host, port, path, urlProto);
+ std::shared_ptr<Subscription> subValue = std::make_shared<Subscription>(
+ host, port, path, urlProto, app.ioContext());
subValue->destinationUrl = destUrl;
diff --git a/src/webserver_main.cpp b/src/webserver_main.cpp
index d3021a83d0..8150f460ad 100644
--- a/src/webserver_main.cpp
+++ b/src/webserver_main.cpp
@@ -85,11 +85,11 @@ static int run()
redfish::RedfishService redfish(app);
// Create EventServiceManager instance and initialize Config
- redfish::EventServiceManager::getInstance();
+ redfish::EventServiceManager::getInstance(&*io);
#ifdef BMCWEB_ENABLE_REDFISH_AGGREGATION
// Create RedfishAggregator instance and initialize Config
- redfish::RedfishAggregator::getInstance();
+ redfish::RedfishAggregator::getInstance(&*io);
#endif
#endif