Skip to content

Commit

Permalink
Open getaddrinfo for public use (#350)
Browse files Browse the repository at this point in the history
* Open getaddrinfo for public use

* Add `getaddrinfo` to `service_discovery`

* getaddrinfo could be returing more than one ipaddress if it fall back to use the host_addresses function
  • Loading branch information
lo-simon authored Nov 2, 2023
1 parent 4f1844d commit 4bdd15a
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 13 deletions.
27 changes: 27 additions & 0 deletions Development/mdns/service_discovery.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,20 @@ namespace mdns
// the callback must not throw
typedef std::function<bool(const resolve_result&)> resolve_handler;

struct address_result
{
address_result() : ttl(0), interface_id(0) {}
address_result(const std::string& host_name, const std::string& ip_address, std::uint32_t ttl = 0, std::uint32_t interface_id = 0) : host_name(host_name), ip_address(ip_address), ttl(ttl), interface_id(interface_id) {}

std::string host_name;
std::string ip_address;
std::uint32_t ttl;
std::uint32_t interface_id;
};

// return true from the address result callback if the operation should be ended before its specified timeout once no more results are "imminent"
typedef std::function<bool(const address_result&)> address_handler;

class service_discovery
{
public:
Expand All @@ -63,6 +77,7 @@ namespace mdns

pplx::task<bool> browse(const browse_handler& handler, const std::string& type, const std::string& domain, std::uint32_t interface_id, const std::chrono::steady_clock::duration& timeout, const pplx::cancellation_token& token = pplx::cancellation_token::none());
pplx::task<bool> resolve(const resolve_handler& handler, const std::string& name, const std::string& type, const std::string& domain, std::uint32_t interface_id, const std::chrono::steady_clock::duration& timeout, const pplx::cancellation_token& token = pplx::cancellation_token::none());
pplx::task<bool> getaddrinfo(const address_handler& handler, const std::string& host_name, std::uint32_t interface_id, const std::chrono::steady_clock::duration& timeout, const pplx::cancellation_token& token = pplx::cancellation_token::none());

template <typename Rep = std::chrono::seconds::rep, typename Period = std::chrono::seconds::period>
pplx::task<bool> browse(const browse_handler& handler, const std::string& type, const std::string& domain = {}, std::uint32_t interface_id = 0, const std::chrono::duration<Rep, Period>& timeout = std::chrono::seconds(default_timeout_seconds), const pplx::cancellation_token& token = pplx::cancellation_token::none())
Expand All @@ -74,6 +89,11 @@ namespace mdns
{
return resolve(handler, name, type, domain, interface_id, std::chrono::duration_cast<std::chrono::steady_clock::duration>(timeout), token);
}
template <typename Rep = std::chrono::seconds::rep, typename Period = std::chrono::seconds::period>
pplx::task<bool> getaddrinfo(const address_handler& handler, const std::string& host_name, std::uint32_t interface_id = 0, const std::chrono::duration<Rep, Period>& timeout = std::chrono::seconds(default_timeout_seconds), const pplx::cancellation_token& token = pplx::cancellation_token::none())
{
return getaddrinfo(handler, host_name, interface_id, std::chrono::duration_cast<std::chrono::steady_clock::duration>(timeout), token);
}

template <typename Rep = std::chrono::seconds::rep, typename Period = std::chrono::seconds::period>
pplx::task<std::vector<browse_result>> browse(const std::string& type, const std::string& domain = {}, std::uint32_t interface_id = 0, const std::chrono::duration<Rep, Period>& timeout = std::chrono::seconds(default_timeout_seconds), const pplx::cancellation_token& token = pplx::cancellation_token::none())
Expand All @@ -89,6 +109,13 @@ namespace mdns
return resolve([results](const resolve_result& result) { results->push_back(result); return true; }, name, type, domain, interface_id, std::chrono::duration_cast<std::chrono::steady_clock::duration>(timeout), token)
.then([results](bool) { return std::move(*results); });
}
template <typename Rep = std::chrono::seconds::rep, typename Period = std::chrono::seconds::period>
pplx::task<std::vector<address_result>> getaddrinfo(const std::string& host_name, std::uint32_t interface_id = 0, const std::chrono::duration<Rep, Period>& timeout = std::chrono::seconds(default_timeout_seconds), const pplx::cancellation_token& token = pplx::cancellation_token::none())
{
std::shared_ptr<std::vector<address_result>> results(new std::vector<address_result>());
return getaddrinfo([results](const address_result& result) {results->push_back(result); return true; }, host_name, interface_id, std::chrono::duration_cast<std::chrono::steady_clock::duration>(timeout), token)
.then([results](bool) { return std::move(*results); });
}

service_discovery(service_discovery&& other);
service_discovery& operator=(service_discovery&& other);
Expand Down
32 changes: 19 additions & 13 deletions Development/mdns/service_discovery_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,19 +200,6 @@ namespace mdns_details
}
}

struct address_result
{
address_result(const std::string& host_name, const std::string& ip_address, std::uint32_t ttl = 0, std::uint32_t interface_id = 0) : host_name(host_name), ip_address(ip_address), ttl(ttl), interface_id(interface_id) {}

std::string host_name;
std::string ip_address;
std::uint32_t ttl;
std::uint32_t interface_id;
};

// return true from the address result callback if the operation should be ended before its specified timeout once no more results are "imminent"
typedef std::function<bool(const address_result&)> address_handler;

#ifdef HAVE_DNSSERVICEGETADDRINFO
struct getaddrinfo_context
{
Expand Down Expand Up @@ -520,6 +507,20 @@ namespace mdns
}, token);
}

pplx::task<bool> getaddrinfo(const address_handler& handler, const std::string& host_name, std::uint32_t interface_id, const std::chrono::steady_clock::duration& timeout, const pplx::cancellation_token& token) override
{
auto gate_ = &this->gate;
return pplx::create_task([=]
{
cancellation_guard guard(token);
auto result = mdns_details::getaddrinfo(handler, host_name, interface_id, timeout, guard.target, *gate_);
// when this task is cancelled, make sure it doesn't just return an empty/partial result
if (token.is_canceled()) pplx::cancel_current_task();
// hmm, perhaps should throw an exception on timeout, rather than returning an empty result?
return result;
}, token);
}

private:
slog::base_gate& gate;
};
Expand Down Expand Up @@ -562,4 +563,9 @@ namespace mdns
{
return impl->resolve(handler, name, type, domain, interface_id, timeout, token);
}

pplx::task<bool> service_discovery::getaddrinfo(const address_handler& handler, const std::string& host_name, std::uint32_t interface_id, const std::chrono::steady_clock::duration& timeout, const pplx::cancellation_token& token)
{
return impl->getaddrinfo(handler, host_name, interface_id, timeout, token);
}
}
1 change: 1 addition & 0 deletions Development/mdns/service_discovery_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace mdns

virtual pplx::task<bool> browse(const browse_handler& handler, const std::string& type, const std::string& domain, std::uint32_t interface_id, const std::chrono::steady_clock::duration& timeout, const pplx::cancellation_token& token) = 0;
virtual pplx::task<bool> resolve(const resolve_handler& handler, const std::string& name, const std::string& type, const std::string& domain, std::uint32_t interface_id, const std::chrono::steady_clock::duration& timeout, const pplx::cancellation_token& token) = 0;
virtual pplx::task<bool> getaddrinfo(const address_handler& handler, const std::string& host_name, std::uint32_t interface_id, const std::chrono::steady_clock::duration& timeout, const pplx::cancellation_token& token) = 0;
};
}
}
Expand Down
15 changes: 15 additions & 0 deletions Development/mdns/test/mdns_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,10 @@ namespace
{
return pplx::task_from_result(false);
}
pplx::task<bool> getaddrinfo(const mdns::address_handler& handler, const std::string& host_name, std::uint32_t interface_id, const std::chrono::steady_clock::duration& timeout, const pplx::cancellation_token& token) override
{
return pplx::task_from_result(false);
}

slog::base_gate& gate;
};
Expand All @@ -415,3 +419,14 @@ BST_TEST_CASE(testMdnsImpl)
advertiser.close().wait();
BST_REQUIRE(gate.hasLogMessage("Close"));
}

////////////////////////////////////////////////////////////////////////////////////////////
BST_TEST_CASE(testDnsGetAddrInfo)
{
test_gate gate;

mdns::service_discovery discover(gate);
auto results = discover.getaddrinfo("google-public-dns-a.google.com").get();
BST_REQUIRE(!results.empty());
BST_REQUIRE_EQUAL("8.8.8.8", results[0].ip_address);
}

0 comments on commit 4bdd15a

Please sign in to comment.