xref: /openbmc/bmcweb/include/async_resolve.hpp (revision d8ef9915)
1 #pragma once
2 #include <boost/asio/ip/address.hpp>
3 #include <boost/asio/ip/basic_endpoint.hpp>
4 #include <sdbusplus/message.hpp>
5 
6 #include <charconv>
7 #include <iostream>
8 #include <memory>
9 
10 namespace crow
11 {
12 
13 namespace async_resolve
14 {
15 
16 class Resolver
17 {
18   public:
19     Resolver() = default;
20 
21     ~Resolver() = default;
22 
23     template <typename ResolveHandler>
24     void asyncResolve(const std::string& host, const std::string& port,
25                       ResolveHandler&& handler)
26     {
27         BMCWEB_LOG_DEBUG << "Trying to resolve: " << host << ":" << port;
28         uint64_t flag = 0;
29         crow::connections::systemBus->async_method_call(
30             [host, port, handler{std::move(handler)}](
31                 const boost::system::error_code ec,
32                 const std::vector<
33                     std::tuple<int32_t, int32_t, std::vector<uint8_t>>>& resp,
34                 const std::string& hostName, const uint64_t flagNum) {
35                 std::vector<boost::asio::ip::tcp::endpoint> endpointList;
36                 if (ec)
37                 {
38                     BMCWEB_LOG_ERROR << "Resolve failed: " << ec.message();
39                     handler(ec, endpointList);
40                     return;
41                 }
42                 BMCWEB_LOG_DEBUG << "ResolveHostname returned: " << hostName
43                                  << ":" << flagNum;
44                 // Extract the IP address from the response
45                 for (auto resolveList : resp)
46                 {
47                     std::vector<uint8_t> ipAddress = std::get<2>(resolveList);
48                     boost::asio::ip::tcp::endpoint endpoint;
49                     if (ipAddress.size() == 4) // ipv4 address
50                     {
51                         BMCWEB_LOG_DEBUG << "ipv4 address";
52                         boost::asio::ip::address_v4 ipv4Addr(
53                             {ipAddress[0], ipAddress[1], ipAddress[2],
54                              ipAddress[3]});
55                         endpoint.address(ipv4Addr);
56                     }
57                     else if (ipAddress.size() == 16) // ipv6 address
58                     {
59                         BMCWEB_LOG_DEBUG << "ipv6 address";
60                         boost::asio::ip::address_v6 ipv6Addr(
61                             {ipAddress[0], ipAddress[1], ipAddress[2],
62                              ipAddress[3], ipAddress[4], ipAddress[5],
63                              ipAddress[6], ipAddress[7], ipAddress[8],
64                              ipAddress[9], ipAddress[10], ipAddress[11],
65                              ipAddress[12], ipAddress[13], ipAddress[14],
66                              ipAddress[15]});
67                         endpoint.address(ipv6Addr);
68                     }
69                     else
70                     {
71                         BMCWEB_LOG_ERROR
72                             << "Resolve failed to fetch the IP address";
73                         handler(ec, endpointList);
74                         return;
75                     }
76                     uint16_t portNum;
77                     auto it = std::from_chars(
78                         port.data(), port.data() + port.size(), portNum);
79                     if (it.ec != std::errc())
80                     {
81                         BMCWEB_LOG_ERROR << "Failed to get the Port";
82                         handler(ec, endpointList);
83                         return;
84                     }
85                     endpoint.port(portNum);
86                     BMCWEB_LOG_DEBUG << "resolved endpoint is : " << endpoint;
87                     endpointList.push_back(endpoint);
88                 }
89                 // All the resolved data is filled in the endpointList
90                 handler(ec, endpointList);
91             },
92             "org.freedesktop.resolve1", "/org/freedesktop/resolve1",
93             "org.freedesktop.resolve1.Manager", "ResolveHostname", 0, host,
94             AF_UNSPEC, flag);
95     }
96 };
97 
98 } // namespace async_resolve
99 } // namespace crow
100