diff --git a/README.md b/README.md index 0ed1a18..af1dd29 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ service or service instance. - CI on Circle (Debian GNU/Linux), Travis (Ubuntu Xenial and OSX) and AppVeyor (Windows Server 2016) - Detects new and/or removed network interfaces - Supports multicasting on multiple network interfaces +- Supports reverse address mapping - Handles legacy unicast queries, see #61 ## Getting started diff --git a/src/ServiceDiscovery.cs b/src/ServiceDiscovery.cs index 31e533e..2347102 100644 --- a/src/ServiceDiscovery.cs +++ b/src/ServiceDiscovery.cs @@ -192,6 +192,10 @@ public void QueryUnicastServiceInstances(string service) /// /// Any queries for the service or service instance will be answered with /// information from the profile. + /// + /// Besides adding the profile's resource records to the PTR records are + /// created to support DNS-SD and reverse address mapping (DNS address lookup). + /// /// public void Advertise(ServiceProfile service) { @@ -209,6 +213,8 @@ public void Advertise(ServiceProfile service) { catalog.Add(r, authoritative: true); } + + catalog.IncludeReverseLookupRecords(); } /// @@ -255,7 +261,9 @@ void OnAnswer(object sender, MessageEventArgs e) } // Any DNS-SD answers? - var sd = msg.Answers.OfType(); + var sd = msg.Answers + .OfType() + .Where(ptr => ptr.Name.EndsWith(".local")); foreach (var ptr in sd) { if (ptr.Name == ServiceName) diff --git a/test/ServiceDiscoveryTest.cs b/test/ServiceDiscoveryTest.cs index 144d1f2..d854e7f 100644 --- a/test/ServiceDiscoveryTest.cs +++ b/test/ServiceDiscoveryTest.cs @@ -321,5 +321,49 @@ public void Unadvertise() mdns.Stop(); } } + [TestMethod] + public void ReverseAddressMapping() + { + var service = new ServiceProfile("x9", "_sdtest-1._udp", 1024, new[] { IPAddress.Loopback, IPAddress.IPv6Loopback }); + var arpaAddress = IPAddress.Loopback.GetArpaName(); + var done = new ManualResetEvent(false); + + var mdns = new MulticastService(); + Message response = null; + mdns.NetworkInterfaceDiscovered += (s, e) => + mdns.SendQuery(arpaAddress, DnsClass.IN, DnsType.PTR); + mdns.AnswerReceived += (s, e) => + { + var msg = e.Message; + if (msg.Answers.OfType().Any(p => p.Name == arpaAddress)) + { + response = msg; + done.Set(); + } + }; + try + { + using (var sd = new ServiceDiscovery(mdns)) + { + sd.Advertise(service); + mdns.Start(); + Assert.IsTrue(done.WaitOne(TimeSpan.FromSeconds(1)), "query timeout"); + var answers = response.Answers + .OfType() + .Where(ptr => service.HostName == ptr.DomainName); + foreach (var answer in answers) + { + Assert.AreEqual(arpaAddress, answer.Name); + Assert.IsTrue(answer.TTL > TimeSpan.Zero); + Assert.AreEqual(DnsClass.IN, answer.Class); + } + } + } + finally + { + mdns.Stop(); + } + } + } }