DNSServiceBrowse does not generate events for removed services.

Frederik Juul 1 Reputation point
2020-09-29T12:07:14.9+00:00

The follow application I would expect to generate 2 events - one for the service appearing and one for the service disappearing. To run the application, it needs to be linked with dnsapi.lib.

I can verify using Wireshark that when the service is deregistered, a new packet is sent out with TTL=0, as expected.

#include <iostream>
#include <Windows.h>
#include <WinDNS.h>
#include <atomic>
#include <future>
#include <chrono>
#include <stdexcept>

using namespace std::chrono_literals;

void DnsServiceBrowseCallback(DWORD status, PVOID pQueryContext, PDNS_RECORD pDnsRecord) {
if (status == ERROR_CANCELLED)
return;
if (status == ERROR_SUCCESS) {
if (pQueryContext != nullptr) {
auto tc = static_cast<std::atomic<int>*>(pQueryContext);
(*tc).operator++(); // Increment atomic integer.
}
}

}

void DnsServiceRegisterCallback(DWORD, PVOID pContext, PDNS_SERVICE_INSTANCE) {
if (pContext != nullptr) {
auto p = static_cast<std::promise<bool>*>(pContext);
p->set_value(true);
}
}

void wait_for_dns_action(DWORD(*f)(PDNS_SERVICE_REGISTER_REQUEST, PDNS_SERVICE_CANCEL), DNS_SERVICE_INSTANCE* service) {

auto p = std::promise<bool>();
auto fut = p.get_future();
DNS_SERVICE_REGISTER_REQUEST rq = {
DNS_QUERY_REQUEST_VERSION1,
0,
service,
DnsServiceRegisterCallback,
&p,
0,
false
};

auto reg = f(&rq, nullptr);

if (reg == DNS_REQUEST_PENDING && fut.wait_for(10s) == std::future_status::ready) {
std::cout << "Action completed" << std::endl;
}
else {
throw std::runtime_error("Unable to complete action");
}

}

int main()
{
DNS_SERVICE_CANCEL cancel;
std::atomic<int> times_called = 0;
std::wstring service_type = L"_test._tcp";

DNS_SERVICE_BROWSE_REQUEST brq = {
1,0,service_type.c_str(),DnsServiceBrowseCallback, &times_called
};

auto breq = DnsServiceBrowse(&brq, &cancel);
if (breq != DNS_REQUEST_PENDING) {
throw std::runtime_error("Unable to start browsing");
}

DWORD ipv4 = 0;
std::wstring service_id = L"testservice._test._tcp.local";
auto service = DnsServiceConstructInstance(
service_id.c_str(),
L"",
&ipv4,
nullptr,
12345,
0,
0,
0,
nullptr,
nullptr
);
wait_for_dns_action(DnsServiceRegister, service);
std::cout << "Registered service" << std::endl;

std::cout << "Expected: 1. Actual: " << times_called << std::endl; // Output 1

wait_for_dns_action(DnsServiceDeRegister, service);
std::cout << "Deregistered service" << std::endl;

std::cout << "Expected: 2. Actual: " << times_called << std::endl; // Output: 1

}
Windows development | Windows API - Win32
{count} votes

1 answer

Sort by: Most helpful
  1. Fei Xue - MSFT 1,111 Reputation points
    2020-11-04T09:00:49.263+00:00

    @Frederik Juul , Here is an UWP which you can refer to the following sample which provides a mechanism by which DNS service discovery can work using option 7, ‘Request Specific DeviceInformationKind’ and ‘AssociationEndpointService’:

    https://learn.microsoft.com/en-us/samples/microsoft/windows-universal-samples/DeviceEnumerationAndPairing/

    37471-deviceenum.png

    And if you still need to make DNSServiceBrowse work for this scenario, a incident is recommend so that our engineer could work closely with you to identify the root cause and resolve this issue as soon as possible.

    If the support engineer determines that the issue is the result of a bug the service request will be a no-charge case and you won't be charged. Please refer to this link and click the 'Contact us' to raise the incident.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.