blob: ae73dd394bff945a79c2d10d17e12e4147751d37 [file] [log] [blame]
Sunitha Harish29a82b02021-02-18 15:54:16 +05301#pragma once
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08002#include "dbus_singleton.hpp"
3#include "logging.hpp"
4
Sunitha Harish29a82b02021-02-18 15:54:16 +05305#include <boost/asio/ip/address.hpp>
6#include <boost/asio/ip/basic_endpoint.hpp>
Carson Labrado7e8890c2022-11-23 23:58:01 +00007#include <boost/asio/ip/tcp.hpp>
Sunitha Harish29a82b02021-02-18 15:54:16 +05308#include <sdbusplus/message.hpp>
9
10#include <charconv>
Sunitha Harish29a82b02021-02-18 15:54:16 +053011#include <memory>
12
Sunitha Harish29a82b02021-02-18 15:54:16 +053013namespace async_resolve
14{
15
Ed Tanouse1452be2021-10-04 17:03:52 -070016inline bool endpointFromResolveTuple(const std::vector<uint8_t>& ipAddress,
17 boost::asio::ip::tcp::endpoint& endpoint)
18{
19 if (ipAddress.size() == 4) // ipv4 address
20 {
Ed Tanous62598e32023-07-17 17:06:25 -070021 BMCWEB_LOG_DEBUG("ipv4 address");
Ed Tanouse1452be2021-10-04 17:03:52 -070022 boost::asio::ip::address_v4 ipv4Addr(
23 {ipAddress[0], ipAddress[1], ipAddress[2], ipAddress[3]});
24 endpoint.address(ipv4Addr);
25 }
26 else if (ipAddress.size() == 16) // ipv6 address
27 {
Ed Tanous62598e32023-07-17 17:06:25 -070028 BMCWEB_LOG_DEBUG("ipv6 address");
Ed Tanouse1452be2021-10-04 17:03:52 -070029 boost::asio::ip::address_v6 ipv6Addr(
30 {ipAddress[0], ipAddress[1], ipAddress[2], ipAddress[3],
31 ipAddress[4], ipAddress[5], ipAddress[6], ipAddress[7],
32 ipAddress[8], ipAddress[9], ipAddress[10], ipAddress[11],
33 ipAddress[12], ipAddress[13], ipAddress[14], ipAddress[15]});
34 endpoint.address(ipv6Addr);
35 }
36 else
37 {
Ed Tanous62598e32023-07-17 17:06:25 -070038 BMCWEB_LOG_ERROR("Resolve failed to fetch the IP address");
Ed Tanouse1452be2021-10-04 17:03:52 -070039 return false;
40 }
41 return true;
42}
43
Sunitha Harish29a82b02021-02-18 15:54:16 +053044class Resolver
45{
46 public:
Ed Tanousf8ca6d72022-06-28 12:12:03 -070047 // unused io param used to keep interface identical to
48 // boost::asio::tcp:::resolver
49 explicit Resolver(boost::asio::io_context& /*io*/) {}
Sunitha Harish29a82b02021-02-18 15:54:16 +053050
51 ~Resolver() = default;
52
Ed Tanousecd6a3a2022-01-07 09:18:40 -080053 Resolver(const Resolver&) = delete;
54 Resolver(Resolver&&) = delete;
55 Resolver& operator=(const Resolver&) = delete;
56 Resolver& operator=(Resolver&&) = delete;
57
Ed Tanousf8ca6d72022-06-28 12:12:03 -070058 using results_type = std::vector<boost::asio::ip::tcp::endpoint>;
59
Sunitha Harish29a82b02021-02-18 15:54:16 +053060 template <typename ResolveHandler>
Ed Tanousf8ca6d72022-06-28 12:12:03 -070061 // This function is kept using snake case so that it is interoperable with
62 // boost::asio::ip::tcp::resolver
63 // NOLINTNEXTLINE(readability-identifier-naming)
Ed Tanousa716aa72023-08-01 11:35:53 -070064 void async_resolve(std::string_view host, std::string_view port,
Ed Tanousf8ca6d72022-06-28 12:12:03 -070065 ResolveHandler&& handler)
Sunitha Harish29a82b02021-02-18 15:54:16 +053066 {
Ed Tanous62598e32023-07-17 17:06:25 -070067 BMCWEB_LOG_DEBUG("Trying to resolve: {}:{}", host, port);
Ed Tanousf8ca6d72022-06-28 12:12:03 -070068
69 uint16_t portNum = 0;
70
71 auto it = std::from_chars(&*port.begin(), &*port.end(), portNum);
72 if (it.ec != std::errc())
73 {
Ed Tanous62598e32023-07-17 17:06:25 -070074 BMCWEB_LOG_ERROR("Failed to get the Port");
Ed Tanousf8ca6d72022-06-28 12:12:03 -070075 handler(std::make_error_code(std::errc::invalid_argument),
76 results_type{});
77
78 return;
79 }
80
Sunitha Harish29a82b02021-02-18 15:54:16 +053081 uint64_t flag = 0;
82 crow::connections::systemBus->async_method_call(
Ed Tanousa716aa72023-08-01 11:35:53 -070083 [host{std::string(host)}, portNum,
Ed Tanous8cb2c022024-03-27 16:31:46 -070084 handler = std::forward<ResolveHandler>(handler)](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -080085 const boost::system::error_code& ec,
Sunitha Harish29a82b02021-02-18 15:54:16 +053086 const std::vector<
87 std::tuple<int32_t, int32_t, std::vector<uint8_t>>>& resp,
88 const std::string& hostName, const uint64_t flagNum) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -040089 results_type endpointList;
90 if (ec)
Ed Tanouse1452be2021-10-04 17:03:52 -070091 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -040092 BMCWEB_LOG_ERROR("Resolve failed: {}", ec.message());
93 handler(ec, endpointList);
94 return;
Ed Tanouse1452be2021-10-04 17:03:52 -070095 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -040096 BMCWEB_LOG_DEBUG("ResolveHostname returned: {}:{}", hostName,
97 flagNum);
98 // Extract the IP address from the response
99 for (const std::tuple<int32_t, int32_t, std::vector<uint8_t>>&
100 resolveList : resp)
101 {
102 boost::asio::ip::tcp::endpoint endpoint;
103 endpoint.port(portNum);
104 if (!endpointFromResolveTuple(std::get<2>(resolveList),
105 endpoint))
106 {
107 boost::system::error_code ecErr = make_error_code(
108 boost::system::errc::address_not_available);
109 handler(ecErr, endpointList);
110 }
111 BMCWEB_LOG_DEBUG("resolved endpoint is : {}",
112 endpoint.address().to_string());
113 endpointList.push_back(endpoint);
114 }
115 // All the resolved data is filled in the endpointList
116 handler(ec, endpointList);
117 },
Sunitha Harish29a82b02021-02-18 15:54:16 +0530118 "org.freedesktop.resolve1", "/org/freedesktop/resolve1",
119 "org.freedesktop.resolve1.Manager", "ResolveHostname", 0, host,
120 AF_UNSPEC, flag);
121 }
122};
123
124} // namespace async_resolve