diff --git a/Development/mdns/service_discovery.h b/Development/mdns/service_discovery.h index d3700d74a..7d89f50d3 100644 --- a/Development/mdns/service_discovery.h +++ b/Development/mdns/service_discovery.h @@ -55,6 +55,20 @@ namespace mdns // the callback must not throw typedef std::function 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 address_handler; + class service_discovery { public: @@ -63,6 +77,7 @@ namespace mdns pplx::task 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 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 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 pplx::task browse(const browse_handler& handler, const std::string& type, const std::string& domain = {}, std::uint32_t interface_id = 0, const std::chrono::duration& timeout = std::chrono::seconds(default_timeout_seconds), const pplx::cancellation_token& token = pplx::cancellation_token::none()) @@ -74,6 +89,11 @@ namespace mdns { return resolve(handler, name, type, domain, interface_id, std::chrono::duration_cast(timeout), token); } + template + pplx::task getaddrinfo(const address_handler& handler, const std::string& host_name, std::uint32_t interface_id = 0, const std::chrono::duration& 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(timeout), token); + } template pplx::task> browse(const std::string& type, const std::string& domain = {}, std::uint32_t interface_id = 0, const std::chrono::duration& timeout = std::chrono::seconds(default_timeout_seconds), const pplx::cancellation_token& token = pplx::cancellation_token::none()) @@ -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(timeout), token) .then([results](bool) { return std::move(*results); }); } + template + pplx::task> getaddrinfo(const std::string& host_name, std::uint32_t interface_id = 0, const std::chrono::duration& timeout = std::chrono::seconds(default_timeout_seconds), const pplx::cancellation_token& token = pplx::cancellation_token::none()) + { + std::shared_ptr> results(new std::vector()); + return getaddrinfo([results](const address_result& result) {results->push_back(result); return true; }, host_name, interface_id, std::chrono::duration_cast(timeout), token) + .then([results](bool) { return std::move(*results); }); + } service_discovery(service_discovery&& other); service_discovery& operator=(service_discovery&& other); diff --git a/Development/mdns/service_discovery_impl.cpp b/Development/mdns/service_discovery_impl.cpp index 18934076e..aaf8a2f8a 100644 --- a/Development/mdns/service_discovery_impl.cpp +++ b/Development/mdns/service_discovery_impl.cpp @@ -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 address_handler; - #ifdef HAVE_DNSSERVICEGETADDRINFO struct getaddrinfo_context { @@ -520,6 +507,20 @@ namespace mdns }, token); } + pplx::task 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; }; @@ -562,4 +563,9 @@ namespace mdns { return impl->resolve(handler, name, type, domain, interface_id, timeout, token); } + + pplx::task 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); + } } diff --git a/Development/mdns/service_discovery_impl.h b/Development/mdns/service_discovery_impl.h index a6050bf66..e1406795c 100644 --- a/Development/mdns/service_discovery_impl.h +++ b/Development/mdns/service_discovery_impl.h @@ -14,6 +14,7 @@ namespace mdns virtual pplx::task 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 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 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; }; } } diff --git a/Development/mdns/test/mdns_test.cpp b/Development/mdns/test/mdns_test.cpp index afda730e5..473a07d3a 100644 --- a/Development/mdns/test/mdns_test.cpp +++ b/Development/mdns/test/mdns_test.cpp @@ -392,6 +392,10 @@ namespace { return pplx::task_from_result(false); } + pplx::task 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; }; @@ -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); +}