Giter Site home page Giter Site logo

net-mdns's Introduction

net-mdns

build status travis build CircleCI Coverage Status Version docs

A simple Multicast Domain Name Service based on RFC 6762. Can be used as both a client (sending queries) or a server (responding to queries).

A higher level DNS Service Discovery based on RFC 6763 that automatically responds to any query for the service or service instance.

Features

  • Targets Framework 4.6.1, .NET Standard 1.4 and 2.0
  • Supports IPv6 and IPv4 platforms
  • 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
  • Supports service subtypes (features)
  • Handles legacy unicast queries, see #61

Getting started

Published releases are available on NuGet. To install, run the following command in the Package Manager Console

PM> Install-Package Makaretu.Dns.Multicast

or using .NET CLI run the following command in the project folder

> dotnet add package Makaretu.Dns.Multicast

Usage Service Discovery

Advertising

Always broadcast the service ("foo") running on local host with port 1024.

using Makaretu.Dns;

var service = new ServiceProfile("x", "_foo._tcp", 1024);
var sd = new ServiceDiscovery();
sd.Advertise(service);

See the example advertiser for a working program.

Discovery

Find all services running on the local link.

using Makaretu.Dns;

var sd = new ServiceDiscovery();
sd.ServiceDiscovered += (s, serviceName) => { // Do something };

Find all service instances running on the local link.

using Makaretu.Dns;

var sd = new ServiceDiscovery();
sd.ServiceInstanceDiscovered += (s, e) => { // Do something };

See the example browser for a working program.

Usage Multicast

Event Based Queries

Get all the Apple TVs. The query is sent when a network interface is discovered. The AnsweredReceived callback contains any answer that is seen, not just the answer to the specific query.

using Makaretu.Dns;

var mdns = new MulticastService();
mdns.NetworkInterfaceDiscovered += (s, e) => mdns.SendQuery("appletv.local");
mdns.AnswerReceived += (s, e) => { // do something with e.Message };
mdns.Start();

Async Queries

Get the first answer to Apple TVs. Wait 2 seconds for an answer.

using Makaretu.Dns;

var service = "appletv.local";
var query = new Message();
query.Questions.Add(new Question { Name = service, Type = DnsType.ANY });
var cancellation = new CancellationTokenSource(2000);

using (var mdns = new MulticastService())
{
    mdns.Start();
    var response = await mdns.ResolveAsync(query, cancellation.Token);
    // Do something
}

Broadcasting

Respond to a query for the service. Note that ServiceDiscovery.Advertise is much easier.

using Makaretu.Dns;

var service = "...";
var mdns = new MulticastService();
mdns.QueryReceived += (s, e) =>
{
    var msg = e.Message;
    if (msg.Questions.Any(q => q.Name == service))
    {
        var res = msg.CreateResponse();
        var addresses = MulticastService.GetIPAddresses()
            .Where(ip => ip.AddressFamily == AddressFamily.InterNetwork);
        foreach (var address in addresses)
        {
            res.Answers.Add(new ARecord
            {
                Name = service,
                Address = address
            });
        }
        mdns.SendAnswer(res);
    }
};
mdns.Start();

Related projects

  • net-dns - DNS data model and Name Server with serializer for the wire and master file format
  • net-udns - client for unicast DNS, DNS over HTTPS (DOH) and DNS over TLS (DOT)

License

Copyright © 2018-2019 Richard Schneider ([email protected])

The package is licensed under the MIT license. Refer to the LICENSE file for more information.

Buy Me A Coffee

net-mdns's People

Contributors

benoitjadinon avatar eshvatskyi avatar gilzad avatar luai-michlawi avatar marloe avatar nickacpt avatar richardschneider avatar xcodo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

net-mdns's Issues

Shutdown exception

When testing IPFS engine disposing, the following exception is thrown.

11:15:49.334 [ERROR] Makaretu.Dns.MulticastService - Receive handler failed
=======================================================(inner most exception)===
 (1) System.NullReferenceException
================================================================================
Method        :  Send
Type          :  Makaretu.Dns.MulticastService
Assembly      :  Makaretu.Dns.Multicast, Version=0.17.2.0, Culture=neutral, PublicKeyToken=null
Assembly Path :  C:\Users\Owner\Documents\GitHub\net-ipfs-engine\test\bin\Debug\net461\Makaretu.Dns.Multicast.dll
Source        :  Makaretu.Dns.Multicast
Thread        :  15 ''
Helplink      :  

Message:
"Object reference not set to an instance of an object."

Stack Trace:
   at Makaretu.Dns.MulticastService.Send(Message msg, Boolean checkDuplicate)
   at Makaretu.Dns.MulticastService.SendAnswer(Message answer, Boolean checkDuplicate)
   at Makaretu.Dns.ServiceDiscovery.OnQuery(Object sender, MessageEventArgs e)
   at System.EventHandler`1.Invoke(Object sender, TEventArgs e)
   at Makaretu.Dns.MulticastService.OnDnsMessage(Object sender, UdpReceiveResult result)
================================================================================

"RecentMessages" not thread safe.

I get a lot of silent exceptions thrown by the MD5 hash algorithm. You can see these exceptions by either enabling "System.Security.Cryptography.ChryptographicException" in debug exception settings or by adding a handler to TaskScheduler.UnobservedTaskException.
It's because the ComputeHash is not thread safe. I suggest to not reuse the created MD5 object and instead create it each time when calculating hash.
So:

using (HashAlgorithm hasher = MD5.Create())
{
return Convert.ToBase64String(hasher.ComputeHash(message));
}

.NET Core support?

Is there a reason why .NET Core is not a target platform? The current .NET direction seems very focused on the Core platform, especially for crossplatform environments, eg Linux/Mac.

I am developing .NET on a Mac and would very much appreciate being able to use the Core target.

Example: Updating a record

I need to be able to update records after they are being advertised, but cannot figure out how. This seems like it would be a fairly common requirement, so an example would go a long ways.

Two or more network interfaces fails after the first

When having two or more network interfaces (only tested on MacOS), adding membership to the second will fail with the following exception:

{System.Net.Sockets.SocketException (0x80004005): Address already in use
at System.Net.Sockets.Socket.SetSocketOption (System.Net.Sockets.SocketOptionLevel optionLevel, System.Net.Sockets.SocketOptionName optionName, System.Object optionValue) [0x000ee] in /Users/builder/jenkins/workspace/build-package-osx-mono/2017-12/external/bockbuild/builds/mono-x64/mcs/class/System/System.Net.Sockets/Socket.cs:2461
at Makaretu.Dns.MulticastService.FindNetworkInterfaces () [0x0022b] in /Users/ml/Projects/DebugPad/net-mdns/src/MulticastService.cs:271 }
base: {System.ComponentModel.Win32Exception}
ErrorCode: 10048
Message: "Address already in use"
SocketErrorCode: System.Net.Sockets.SocketError.AddressAlreadyInUse
Non-public members:

Instance names

From RFC 6763 section 4.1.1

The portion of the Service Instance Name is a user-
friendly name consisting of arbitrary Net-Unicode text [RFC5198]. It
MUST NOT contain ASCII control characters (byte values 0x00-0x1F and
0x7F) [RFC20] but otherwise is allowed to contain any characters,
without restriction, including spaces, uppercase, lowercase,
punctuation -- including dots -- accented characters, non-Roman text,
and anything else that may be represented using Net-Unicode.

See also #64

Host names and underscore

A hostname cannot contain an underscore (_). ServiceProfile should replace "_" with "-" when generating a default host name.

Helps with #64

Advertising issues

very strange.
can not get stable recorn when browsing my local mdns.
sometimes record appears after 10 minutes, and only a top-level.
and browser, in general, had issues with getting other records (takes a lot of time to get all).
after I stopped a project everything works fine.

11/3/2018 2:09:12 AM [DEBUG] Makaretu.Dns.ServiceDiscovery - got query for _services._dns-sd._udp.local PTR
11/3/2018 2:09:12 AM [DEBUG] Makaretu.Dns.ServiceDiscovery - sent answer _services._dns-sd._udp.local IN PTR _hap._tcp.local

Unadvertise a service Takes long time to Release Resources

I can see the Threads being still running and being stopped one by one. I have created 2 buttons for Publish & unpublish. It works fine for the first time if I publish or Unpublish. But if I publish again it takes time to publish. What might be the reason?

Tmds.Libc does dependency does not work with Xamarin.iOS

The dependency on Tmds.Libc introduced to solve #22 breaks building for Xamarin.iOS. This is because when compiling for Xamarin.iOS all referenced assemblies are needed for the linker even if those assemblies will not be used at runtime. However, Tmds.Libc does not deliver any assemblies for Xamarin.iOS.

Perhaps it's possible to use the needed DllImports directly in net-mdns instead of depending on Tmds.Libc.

Npcap Loopback Adapter

When running all the MDNS software locally, everything works correctly. However, when the Npcap Loopback Adapter is enabled on host A and host B sends a QUERY, host B does not get QUERY RESPONSE from host A.

If I disable the adapter, everything works.

Trailing dot in domain missing?

Hello @richardschneider ,

Together with @gaviriar (and others) we intend to use Makaretu.Mdns as a dependency for a protocol that relies on mDNS. After reading RFC6762 our understanding is that for mDNS every service should announce itself with a local domain, however we are not certain if this should be .local or the fully-qualified .local..

In ServiceProfile.cs#L137 it looks like the FullyQualifiedName does not include a trailing ., which makes it (by definition, as I understand it) not fully-qualified, but just relative.

Would you mind having a look at this, to determine if this is a bug?

kind regards,
Michael

Spike: SocketException: Address already in use when running on Ubuntu

Hi There,

I was testing the Spike sample application on Linux, the code builds but when I try to run it I get the following exception:

Multicast DNS spike
IP address 192.168.1.108
IP address fe80::913d:56ef:385b:60a3%3
8/15/18 6:26:18 PM [DEBUG] Makaretu.Dns.MulticastService - Found nic 'wlp1s0'.

Unhandled Exception: discovered NIC 'wlp1s0'
System.Net.Sockets.SocketException: Address already in use
  at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName)
  at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
  at System.Net.Sockets.Socket.Bind(EndPoint localEP)
  at Makaretu.Dns.MulticastService.Listener() in /home/unitelabs/Desktop/unitelabs/local/net-mdns/src/MulticastService.cs:line 524
  at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
  at System.Threading.ThreadPoolWorkQueue.Dispatch()

Built On

OS: Ubuntu 18.04
cli version: .NET Command Line Tools (2.1.302)
dotnet version: netcoreapp2.0

Just some additional information, it seems that the exception is thrown here when trying to bind to the MultiCast port 5353. When checking the list of processes that own port 5353 sudo lsof -i :5353 I get the following output:

COMMAND    PID      USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
avahi-dae 1138     avahi   12u  IPv4   1695      0t0  UDP *:mdns 
avahi-dae 1138     avahi   13u  IPv6   1696      0t0  UDP *:mdns 
chrome    2988 unitelabs  120u  IPv4  84340      0t0  UDP *:mdns 
chrome    2988 unitelabs  157u  IPv6  84341      0t0  UDP *:mdns 

Any clues or suggestions why this might be the case? Secondly, do you plan to provide support on linux for this library?

Regards,
Ricardo

Not responding to "QU" questions

@gaviriar and I discovered a problem with queries. A service was not responding to PTR queries issued by a Java client, while responding to PTR queries originating from a C# client that uses this library.

grafik

The corresponding log (awesome logging, by the way!) shows that all queries were received, but a response was only sent for the first:

grafik

Upon investgation with Wireshark, I found that the two libraries (this one vs. the Java alternative) issued different PTR queries:

grafik

So the Java library issued a QU question, as described in RFC6769 section 5.4:

To avoid large floods of potentially unnecessary responses in these
cases, Multicast DNS defines the top bit in the class field of a DNS
question as the unicast-response bit. When this bit is set in a
question, it indicates that the querier is willing to accept unicast
replies in response to this specific query, as well as the usual
multicast responses. These questions requesting unicast responses
are referred to as "QU" questions, to distinguish them from the more
usual questions requesting multicast responses ("QM" questions). A
Multicast DNS querier sending its initial batch of questions
immediately on wake from sleep or interface activation SHOULD set the
unicast-response bit in those questions.

As far as I can tell this is completely okay behavior by the Java client, but net-mdns should have responded.

Since the logger doesn't show any errors, I assume that the condition in ServiceDiscovery.cs#208 is fulfilled and this is some kind of parsing problem, @richardschneider ?

cheers

System.Net.Sockets.SocketException (0x80004005): Address already in use

I am getting this exception when using the latest NuGet version (0.5.0) i Microsoft Visual Studio for Mac.
If I download this repo, and reference the Mdns project directly, it works perfectly.

Unhandled Exception:
System.Net.Sockets.SocketException (0x80004005): Address already in use
  at System.Net.Sockets.Socket.SetSocketOption (System.Net.Sockets.SocketOptionLevel optionLevel, System.Net.Sockets.SocketOptionName optionName, System.Object optionValue) [0x000ee] in /Users/builder/jenkins/workspace/build-package-osx-mono/2017-12/external/bockbuild/builds/mono-x64/mcs/class/System/System.Net.Sockets/Socket.cs:2461 
  at Makaretu.Dns.MulticastService.FindNetworkInterfaces (System.Object state) [0x0013c] in <bad354b0b01c4ec3b13cbe9f835c3cc2>:0 
  at System.Threading.Timer+Scheduler.TimerCB (System.Object o) [0x00007] in /Users/builder/jenkins/workspace/build-package-osx-mono/2017-12/external/bockbuild/builds/mono-x64/mcs/class/corlib/System.Threading/Timer.cs:327 
  at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem () [0x00015] in /Users/builder/jenkins/workspace/build-package-osx-mono/2017-12/external/bockbuild/builds/mono-x64/mcs/class/referencesource/mscorlib/system/threading/threadpool.cs:1279 
  at System.Threading.ThreadPoolWorkQueue.Dispatch () [0x00074] in /Users/builder/jenkins/workspace/build-package-osx-mono/2017-12/external/bockbuild/builds/mono-x64/mcs/class/referencesource/mscorlib/system/threading/threadpool.cs:856 
  at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback () [0x00000] in /Users/builder/jenkins/workspace/build-package-osx-mono/2017-12/external/bockbuild/builds/mono-x64/mcs/class/referencesource/mscorlib/system/threading/threadpool.cs:1211 
[ERROR] FATAL UNHANDLED EXCEPTION: System.Net.Sockets.SocketException (0x80004005): Address already in use
  at System.Net.Sockets.Socket.SetSocketOption (System.Net.Sockets.SocketOptionLevel optionLevel, System.Net.Sockets.SocketOptionName optionName, System.Object optionValue) [0x000ee] in /Users/builder/jenkins/workspace/build-package-osx-mono/2017-12/external/bockbuild/builds/mono-x64/mcs/class/System/System.Net.Sockets/Socket.cs:2461 
  at Makaretu.Dns.MulticastService.FindNetworkInterfaces (System.Object state) [0x0013c] in <bad354b0b01c4ec3b13cbe9f835c3cc2>:0 
  at System.Threading.Timer+Scheduler.TimerCB (System.Object o) [0x00007] in /Users/builder/jenkins/workspace/build-package-osx-mono/2017-12/external/bockbuild/builds/mono-x64/mcs/class/corlib/System.Threading/Timer.cs:327 
  at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem () [0x00015] in /Users/builder/jenkins/workspace/build-package-osx-mono/2017-12/external/bockbuild/builds/mono-x64/mcs/class/referencesource/mscorlib/system/threading/threadpool.cs:1279 
  at System.Threading.ThreadPoolWorkQueue.Dispatch () [0x00074] in /Users/builder/jenkins/workspace/build-package-osx-mono/2017-12/external/bockbuild/builds/mono-x64/mcs/class/referencesource/mscorlib/system/threading/threadpool.cs:856 
  at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback () [0x00000] in /Users/builder/jenkins/workspace/build-package-osx-mono/2017-12/external/bockbuild/builds/mono-x64/mcs/class/referencesource/mscorlib/system/threading/threadpool.cs:1211 

Legacy Unicast Responses

6.7. Legacy Unicast Responses

If the source UDP port in a received Multicast DNS query is not port
5353, this indicates that the querier originating the query is a
simple resolver such as described in Section 5.1, "One-Shot Multicast
DNS Queries", which does not fully implement all of Multicast DNS.
In this case, the Multicast DNS responder MUST send a UDP response
directly back to the querier, via unicast, to the query packet's
source IP address and port. This unicast response MUST be a
conventional unicast response as would be generated by a conventional
Unicast DNS server; for example, it MUST repeat the query ID and the
question given in the query message. In addition, the cache-flush
bit described in Section 10.2, "Announcements to Flush Outdated Cache
Entries", MUST NOT be set in legacy unicast responses.

The resource record TTL given in a legacy unicast response SHOULD NOT
be greater than ten seconds, even if the true TTL of the Multicast
DNS resource record is higher. This is because Multicast DNS
responders that fully participate in the protocol use the cache
coherency mechanisms described in Section 10, "Resource Record TTL
Values and Cache Coherency", to update and invalidate stale data.
Were unicast responses sent to legacy resolvers to use the same high
TTLs, these legacy resolvers, which do not implement these cache
coherency mechanisms, could retain stale cached resource record data
long after it is no longer valid.

Responding to address queries

From https://tools.ietf.org/html/rfc6762#section-6.2

When a Multicast DNS responder sends a Multicast DNS response message
containing its own address records, it MUST include all addresses
that are valid on the interface on which it is sending the message,
and MUST NOT include addresses that are not valid on that interface
(such as addresses that may be configured on the host's other
interfaces). For example, if an interface has both an IPv6 link-
local and an IPv6 routable address, both should be included in the
response message so that queriers receive both and can make their own
choice about which to use. This allows a querier that only has an
IPv6 link-local address to connect to the link-local address, and a
different querier that has an IPv6 routable address to connect to the
IPv6 routable address instead.

Invalid clearing of additional records

if (response.Answers.Any(a => a.Name == ServiceName))

Should be

           // Many bonjour browsers don't like DNS-SD response
            // with additional records.
            if (response.Answers.Any(a => a.Name == ServiceName))
            {
               if (AnswersContainsAdditionalRecords)
               {
                   response.Answers.AddRange(response.AdditionalRecords);
               }
                response.AdditionalRecords.Clear();
            }

Negative answers

A Multicast DNS responder MUST only respond when it has a positive,
non-null response to send, or it authoritatively knows that a
particular record does not exist. For unique records, where the host
has already established sole ownership of the name, it MUST return
negative answers to queries for records that it knows not to exist.
For example, a host with no IPv6 address, that has claimed sole
ownership of the name "host.local." for all rrtypes, MUST respond to
AAAA queries for "host.local." by sending a negative answer
indicating that no AAAA records exist for that name. See Section
6.1, "Negative Responses". For shared records, which are owned by no
single host, the nonexistence of a given record is ascertained by the
failure of any machine to respond to the Multicast DNS query, not by
any explicit negative response. For shared records, NXDOMAIN and
other error responses MUST NOT be sent.

Network interface discovery

Rename the event NetworkInterfaceDiscovered to NetworkChanged. The args should containt the current NICs, the removed NICs and the added NICs.

MDNS does not start in UWP app

I was always looking for a MDNS library that can query and announce services at the same time. Seems your library could be the perfect match. :)

While I got it running within .NET 4.6.1, it seems no to work for a Windows 10 UWP app.
I took your browser sample from here: https://github.com/richardschneider/net-mdns/blob/master/Browser/Program.cs

I have set all neccessary capabilities for private network and so on, and I split the code into one half setting up handlers and starting the service and another half that stops and disposes.

But unfortunately it seems the multicast service does not even start.
First I realized I never get the NetworkInterfaceDiscovered event... so I added another button for testing purposes which shall do the query anyway - but this one always throws an exception that mdns got not started. So I am wondering what could block mdns.start(); internally from starting?

Can anyone confirm this for UWP?

NSEC records with parameter Types

How to send answer of Record type NSEC with types TXT and SRV.

Something like this , I found this in ARSoft.Tools.Net
public NSecRecord(string name, RecordClass recordClass, int timeToLive, string nextDomainName, List types): base(name, RecordType.NSec, recordClass, timeToLive)
{
}

Network changed

@cerna got a System.OutOfMemoryException when running .Net Core 3.0 (preview) on a Debian Stretch. The stack track indicates that NetworkAddressChanged was involved. While this may just be an issue with the preview release; it could mean something is wrong with our code.

I've never liked the code that removes and then adds the NetworkAddressChanged event handler.

Ability to restrict service querying to specific network interface.

Just like the mDNS advertising can be restricted to specific IPAddresses, it would consistent to do the same for queries.

This is a feature request for the ability to restrict both service advertising and service discovery to a set of network interfaces.

Motivation

The situation in my case is a computer that is connected to two networks. I ran into a lot of trouble, because the current implementation attempts to use all network interfaces simultaneously:

  • no exception is raised when the UdpClient can not be created on a particular interface
  • there is no way to restrict activity to a particular interface
  • a firewall configuration can prevent the program from opening a port on some interfaces

Proposed solution

Support for restricting activity to a specific network interface could be implemented via a NetworkInterfaces[] parameter to the constructor of the MulticastService.

MacOS : not connected network interfaces

on mac, you can have nics that are 'up' (enabled) but not connected (unplugged), like ethernet for example.

any idea how to find a reliable way to see if the nic is connected or not ?

quick fix : checking if it has an ip address :

protected static IEnumerable<NetworkInterface> GetNetworkInterfaces()
            {
                return NetworkInterface.GetAllNetworkInterfaces()
                    .Where(nic => nic.OperationalStatus == OperationalStatus.Up)
                    .Where(nic => nic.NetworkInterfaceType != NetworkInterfaceType.Loopback && nic.NetworkInterfaceType != NetworkInterfaceType.Unknown)
                    .Where(nic => nic.SupportsMulticast)
                    .Where(nic => nic.GetIPProperties().UnicastAddresses.Any(information => information.Address.AddressFamily == AddressFamily.InterNetwork || information.Address.AddressFamily == AddressFamily.InterNetworkV6))
                    ;
            }

ServiceInstanceShutdown event

Add a ServiceInstanceShutdown event to ServiceDiscovery. It should be raised when OnAnswer sees a service instance PTR with a zero TTL.

See also #47

Can't discover any device

I tried to use this library, however I am unable to find any device. Neither the local service nor my printer are visible. What I am doing wrong? (I am using VS2017 and downloaded net-mdns via nuget as well as it's dependencies...). The code you see bellow is the modified test code.
Thank you!

    public static void Main(string[] args)
    {
        var service = new ServiceProfile("x", "_sdtest-2._tcp", 1024);
        var mdns = new MulticastService();
        var sd = new ServiceDiscovery(mdns);

        mdns.NetworkInterfaceDiscovered += (s, e) =>
        {
            Console.WriteLine("found" + s + e);
            sd.QueryAllServices();
        };

        sd.ServiceDiscovered += (s, serviceName) =>
        {
            Console.WriteLine("found" + s + serviceName);
        };
        try
        {
            sd.Advertise(service);
            mdns.Start();
            Console.ReadKey();
        }
        finally
        {
            sd.Dispose();
            mdns.Stop();
        }            
    }


}

Associate address records

When a Multicast DNS responder places an IPv4 or IPv6 address record
(rrtype "A" or "AAAA") into a response message, it SHOULD also place
any records of the other address type with the same name into the
additional section, if there is space in the message.

I got this unhandled exception when I have attached the TaskScheduler.UnobservedTaskException:

I got this unhandled exception when I have attached the TaskScheduler.UnobservedTaskException:


   SocketException: A request to send or receive data was disallowed because the socket had already been shut down in that direction with a previous shutdown call
   at System.Net.Sockets.Socket.DoBeginReceiveFrom(Byte[], Int32, Int32, System.Net.Sockets.SocketFlags, System.Net.EndPoint, System.Net.SocketAddress, System.Net.Sockets.OverlappedAsyncResult);System.dll;100671645;212
   at System.Net.Sockets.Socket.BeginReceiveFrom(Byte[], Int32, Int32, System.Net.Sockets.SocketFlags, System.Net.EndPoint ByRef, System.AsyncCallback, System.Object);System.dll;100671644;270
   at System.Net.Sockets.UdpClient.BeginReceive(System.AsyncCallback, System.Object);System.dll;100671973;42
   at System.Threading.Tasks.TaskFactory`1.FromAsyncImpl(System.Func`3[System.AsyncCallback,System.Object,System.IAsyncResult], System.Func`2[System.IAsyncResult,TResult], System.Action`1[System.IAsyncResult], System.Object, System.Threading.Tasks.TaskCreationOptions);mscorlib.dll;100679367;304
   at System.Net.Sockets.UdpClient.ReceiveAsync();System.dll;100671984;17
   at Makaretu.Dns.MulticastClient+<>c__DisplayClass13_0+<<Listen>b__0>d.MoveNext();Makaretu.Dns.Multicast.dll;100663321;23 

@richardschneider does #81 also fix this. If not maybe the receive code should catch all exceptions?

Originally posted by @Luai-m in #79 (comment)

Not working on android & iOS (Unity)

Hi,
Iv got the mDNS working within the editor of unity. But once i build and run on android or iOS devices, it doesn't work.

There is no errors or log messages, do you have any idea why this might be happening?

Thanks!

Service Discovery goodbye message

Hello,
looking at ServiceDiscovery.Advertise() method to announce new service I don't see any way how to deannounce announced service. Typical way of doing this is to send a type of "goodbye message" where the Time-To-Live property is set to zero so listeners can update theirs records and take these services out of the roster.

On the same line when disposing of ServiceDiscovery object, there is no clean up. So services will "appear" alive to the end ot TTL, which could be a while.

Theoretically I can do something dirty like this:

ServiceProfile service = new ServiceProfile("x1", "_xservice._tcp", 5011);
sd.Advertise(service);
mdns.Start();
service.Resources.ForEach(s => { s.TTL = TimeSpan.Zero; });

Hovewer then it will still stay in DNS server collection.

Allow dot in service name

In Bonjour, Avahi and a commit to Jmdns it is possible to not only have a typical service like:
instance._serviceType._protocol._domain
but also
instance._subinstance._serviceType._protocol._domain

I've tried that concatenation in net-mdns but then avahi won't resolve the service and Bonjour won't even find the published service (i.e. doesn't react to PTR or SRV). Upon investigation the domain-part in the PTR-record seems stripped.

Answers
	_itxpt_http._tcp.local: type PTR, class IN, TST-PC._fmstoip-add
		Name: _itxpt_http._tcp.local
		Type: PTR (domain name PoinTeR) (12)
		.000 0000 0000 0001 = Class: IN (0x0001)
		0... .... .... .... = Cache flush: False
		Time to live: 4500
		Data length: 23
		Domain Name: TST-PC._fmstoip-add
Additional records
	TST-PC._fmstoip-add: type SRV, class IN, priority 0, weight 0, port 8085, target TST-PC._fmstoip-add
		Service: TST-PC
		Protocol: _fmstoip-add
		Type: SRV (Server Selection) (33)
		.000 0000 0000 0001 = Class: IN (0x0001)
		0... .... .... .... = Cache flush: False
		Time to live: 4500
		Data length: 40
		Priority: 0
		Weight: 0
		Port: 8085
		Target: TST-PC._fmstoip-add

In comparison that's how Bonjour advertises its service like this:

Answers
	_services._dns-sd._udp.local: type PTR, class IN, _itxpt_http._tcp.local
		Name: _services._dns-sd._udp.local
		Type: PTR (domain name PoinTeR) (12)
		.000 0000 0000 0001 = Class: IN (0x0001)
		0... .... .... .... = Cache flush: False
		Time to live: 4500
		Data length: 2
		Domain Name: _itxpt_http._tcp.local
	_itxpt_http._tcp.local: type PTR, class IN, TST-PC._fmstoip-add._itxpt_http._tcp.local
		Name: _itxpt_http._tcp.local
		Type: PTR (domain name PoinTeR) (12)
		.000 0000 0000 0001 = Class: IN (0x0001)
		0... .... .... .... = Cache flush: False
		Time to live: 4500
		Data length: 2
		Domain Name: TST-PC._fmstoip-add._itxpt_http._tcp.local
	TST-PC._fmstoip-add._itxpt_http._tcp.local: type SRV, class IN, cache flush, priority 0, weight 0, port 8085, target TST-PC.local
		Service: TST-PC
		Protocol: _fmstoip-add
		Name: _itxpt_http._tcp.local
		Type: SRV (Server Selection) (33)
		.000 0000 0000 0001 = Class: IN (0x0001)
		1... .... .... .... = Cache flush: True
		Time to live: 120
		Data length: 15
		Priority: 0
		Weight: 0
		Port: 8085
		Target: TST-PC.local

And Avahi advertises like this:

Answers
	_itxpt_http._tcp.local: type PTR, class IN, TST-PC._fmstoip-add._itxpt_http._tcp.local
		Name: _itxpt_http._tcp.local
		Type: PTR (domain name PoinTeR) (12)
		.000 0000 0000 0001 = Class: IN (0x0001)
		0... .... .... .... = Cache flush: False
		Time to live: 4500
		Data length: 2
		Domain Name: TST-PC._fmstoip-add._itxpt_http._tcp.local
	TST-PC._fmstoip-add._itxpt_http._tcp.local: type SRV, class IN, cache flush, priority 0, weight 0, port 8085, target beaglebone.local
		Service: TST-PC
		Protocol: _fmstoip-add
		Name: _itxpt_http._tcp.local
		Type: SRV (Server Selection) (33)
		.000 0000 0000 0001 = Class: IN (0x0001)
		1... .... .... .... = Cache flush: True
		Time to live: 120
		Data length: 19
		Priority: 0
		Weight: 0
		Port: 8085
		Target: beaglebone.local
	_services._dns-sd._udp.local: type PTR, class IN, _itxpt_http._tcp.local
		Name: _services._dns-sd._udp.local
		Type: PTR (domain name PoinTeR) (12)
		.000 0000 0000 0001 = Class: IN (0x0001)
		0... .... .... .... = Cache flush: False
		Time to live: 4500
		Data length: 2
		Domain Name: _itxpt_http._tcp.local

I'm gladly willing to make a PR as soon as I've figured out what causes any possibly malformed(?) packets. I've chased a lot of suspectations in ServiceProfile() but didn't really gain the understanding to successfully publish a serivce with a name like TST-PC._fmstoip-add. Can I kindly ask for any hint on this?

Duplicate responses

From https://tools.ietf.org/html/rfc6762#section-6

To protect the network against excessive packet flooding due to
software bugs or malicious attack, a Multicast DNS responder MUST NOT
(except in the one special case of answering probe queries) multicast
a record on a given interface until at least one second has elapsed
since the last time that record was multicast on that particular
interface. A legitimate querier on the network should have seen the
previous transmission and cached it. A querier that did not receive
and cache the previous transmission will retry its request and
receive a subsequent response. In the special case of answering
probe queries, because of the limited time before the probing host
will make its decision about whether or not to use the name, a
Multicast DNS responder MUST respond quickly. In this special case
only, when responding via multicast to a probe, a Multicast DNS
responder is only required to delay its transmission as necessary to
ensure an interval of at least 250 ms since the last time the record
was multicast on that interface.

NullReferenceException

First off, thank you for all the work you put into this project; it is fantastic.

I hook TaskScheduler.UnobservedTaskException and I occasionally get null ref exceptions as seen in the following log message. I'm running v2.0.1 (Makaretu.Dns.Multicast package v0.25.0).

   -------------Exception--------------
   Ex Type:      System.AggregateException
   Message:      A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread.
   Source:       
   Method:       
   Data:         
   Stack trace:  
                 ---------More Detail----------
                 AggregateException Inner Ex Count:               1
                 AggregateException Base Ex Type:                 System.NullReferenceException
                 AggregateException Base Ex Method:               Byte[] EndReceive(System.IAsyncResult, System.Net.IPEndPoint ByRef)
                 AggregateException Base Ex Message:              Object reference not set to an instance of an object.
                 AggregateException Base Ex Stack trace:          at System.Net.Sockets.UdpClient.EndReceive(IAsyncResult asyncResult, IPEndPoint& remoteEP)
                     at System.Net.Sockets.UdpClient.<ReceiveAsync>b__64_1(IAsyncResult ar)
                     at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar,
                     Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
                     --- End of stack trace from previous location where
                     exception was thrown ---
                     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
                     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
                     at Makaretu.Dns.MulticastClient.<>c__DisplayClass13_0.<<Listen>b__0>d.MoveNext()
                 ---------Flattened Inner Exceptions 1/1---------
                 InnerException:                 
                     Object reference not set to an instance of an object.

      -------------Inner Exception 1--------------
      Inner Ex Type:     System.NullReferenceException
      Inner Message:     Object reference not set to an instance of an object.
      Inner Source:      System
      Inner Method:      Byte[] EndReceive(System.IAsyncResult, System.Net.IPEndPoint ByRef)
      Inner Data:        System.Collections.ListDictionaryInternal
      Inner Stack trace: at System.Net.Sockets.UdpClient.EndReceive(IAsyncResult asyncResult, IPEndPoint& remoteEP)
                         at System.Net.Sockets.UdpClient.<ReceiveAsync>b__64_1(IAsyncResult ar)
                         at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar,
                         Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
                         --- End of stack trace from previous location where
                         exception was thrown ---
                         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
                         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
                         at Makaretu.Dns.MulticastClient.<>c__DisplayClass13_0.<<Listen>b__0>d.MoveNext()

Not working for multi active NICs

https://stackoverflow.com/questions/6976526/udp-multicasting-with-multiple-nics-only-works-when-one-interface-is-active

  1. it's bonded only to 1 from 3 available and receiving messages only for it.
  2. No need to recreate LISTENER all the time, since there is used IPAddress.ANY. I'm using TCPListener in a project with the same binding. All works without re-creating, when disabling one NIC it's just become unavailable for a subnet, and when enabling it back - it's back online.

Question: Bonjour/ZeroConf support

Hi

Can you tell me if I can use this library to "broadcast" a bonjour / zeroconf service?
I know that the service itself needs to be implemented separately.
But the info needs to be broadcasted so clients can "pick it up".

I am using Bonjour Browser to discover existing Bonjour services.

Thank you for any input you can provide,

Martin

Advertise apparently not working

Hi, I'm trying to use your code to publish an application on my local network. I've tested the browser and advertiser programs but there's maybe something I'm not understanding. The browser program works fine, I can see all the services and whatnot running on my network. I've also made a simple node js script to publish something using zeroconf and as soon as it gets published I can see it with the browser.
My issue lies with the advertiser, do I need bonjour installed? I've tried your program but I can't see anything when also running the browser, is it because I don't have bonjour installed?

Thanks in advance

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.