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
diff --git a/include/async_resolve.hpp b/include/async_resolve.hpp
index f44be4b..5e526ca 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 @@
 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 @@
     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 @@
             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 @@
                     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 @@
 
 } // namespace async_resolve
 } // namespace crow
+#endif