Code Monkey home page Code Monkey logo

zeroconf's Introduction

Zeroconf

Bonjour/mDNS discovery support for .NET v4.8, UWP, Xamarin & .NET Standard 2.0

The core logic is implemented primarily .NET Standard 2.0. Due to networking APIs being platform-specific on earlier platforms, a platform-specific version is required. Just make sure that you also install the NuGet to your main app and you'll be all set.

Installation

The easiest way to get started is to use the NuGet package.

Install-Package Zeroconf

Current Build Status: Build Status

Migration from <= v3.5.11 to >=v3.6

The key of the dictionary IZeroconfHost.Services of type IReadOnlyDictionary<string, IService> that is returned by e.g. ResolveAsync changed. Instead of IService.Name which is the PTR record name, now the name from the SRV record is used which is called ServiceName in IService. This allows to return more than one service of the same type from the same host. If you used the key of this dictonary (e.g. s.Key) for iteration now use s.Value.Name.

Usage

There's are two methods with a few optional parameters:

using Zeroconf;
public async Task ProbeForNetworkPrinters()
{
    IReadOnlyList<IZeroconfHost> results = await
        ZeroconfResolver.ResolveAsync("_printer._tcp.local.");
}

public async Task EnumerateAllServicesFromAllHosts()
{
    ILookup<string, string> domains = await ZeroconfResolver.BrowseDomainsAsync();            
    var responses = await ZeroconfResolver.ResolveAsync(domains.Select(g => g.Key));            
    foreach (var resp in responses)
        Console.WriteLine(resp);
}

The ResolveAsync method has one required and several optional parameters. The method signature is as follows:

Task<IReadOnlyList<IZeroconfHost>> ResolveAsync(string protocol, TimeSpan scanTime = default(TimeSpan), int retries = 2, int retryDelayMilliseconds = 2000, Action<IZeroconfHost> callback = null, CancellationToken cancellationToken = default(CancellationToken), System.Net.NetworkInformation.NetworkInterface[] netInterfacesToSendRequestOn = null);

The BrowseDomainsAsync method has the same set of optional parameters. The method signature is:

Task<ILookup<string, string>> BrowseDomainsAsync(TimeSpan scanTime = default (TimeSpan), int retryDelayMilliseconds = 2000, Action<string, string> callback = null, CancellationToken cancellationToken = default (CancellationToken), System.Net.NetworkInformation.NetworkInterface[] netInterfacesToSendRequestOn = null)

What you get back from the Browse is a lookup, by service name, of a group that contains every host offering that service. Thst most common use would be in the example above, passing in all keys (services) to the Resolve method. Otherwise, you can also see what hosts are offering which services as well.

IObservable

Starting in v2.5, there are two additional methods that return IObservable's instead of Tasks. These methods are otherwise identical to the *Async versions but are more suitable for some usages.

Parameters

Parameter Name Default Value Notes
protocol Service to query. Almost always must end with .local.
scanTime 2 seconds Amount of time to listen for responses
retries 2 Number of times to attempt to bind to the socket. Binding may fail if another app is currently using it.
retryDelayMilliseconds 2000 Delay between retries
callback null If provided, called per IZeroconfigHost as they are processed. This can be used to stream data back prior to call completion.
cancellationToken CancellationToken.None Optional use of task cancellation
netInterfacesToSendRequestOn null Specify a list of network adapters to use. If null is specified, all adapters are used

Notes

The ResolveAsync method is thread-safe, however all calls to it are serialized as only one can be in-progress at a time.

Xamarin.Android 4.x Linker bug

There is currently a bug on Xamarin.Android 4.x that incorrectly strips out internal Socket methods. This has been fixed for the Xamarin.Android 5.0 series. As a workaround on 4.x, entering System; in to the Ignore Assemblies field in the Project Options->Build->Android Build page will fix the problem.

Android

You must call the WifiManager.MulticastLock manager Aquire and Release before/after you call the Zeroconf methods. Previous versions (prior to 2.7 did this internally, now it requires the caller to do it).

Something like this:

// Somewhere early
var wifi = (WifiManager)ApplicationContext.GetSystemService(Context.WifiService);
var mlock = wifi.CreateMulticastLock("Zeroconf lock");

---
// Later, before you call Zeroconf
try
{
  mlock.Acquire();

  // Call Zeroconf
  ZeroconfResolver....
}
finally
{
  mlock.Release();
}

You'll also need to specify the correct permsision like this:

[assembly: UsesPermission(Android.Manifest.Permission.ChangeWifiMulticastState)]

UWP

You'll need to have the following permissions on your manifest depending on what networks you're trying to scan:

  • Private Networks (Client & Server)
  • Internet (Client & Server)

Xamarin.iOS on iOS 14.5+

iOS 14.5 and later introduced new restrictions on mDNS clients. Low-level socket-based clients (like Zeroconf) are blocked at the iOS library/system call level unless the program has a special com.apple.developer.networking.multicast entitlement.

If your app must browse arbitrary/unknown-at-compile-time services, you must obtain the com.apple.developer.networking.multicast entitlement from Apple. If you do obtain the entitlement, somewhere early in your app set the property ZeroconfResolver.UseBSDSocketsZeroconfOniOS to true; this will cause the Zeroconf library to behave as it always has and no workaround code will be executed.

For all other apps that know which mDNS services they must interact with: one way to work around this restriction is to use the iOS NSNetServiceBrowser and NSNetService objects. A workaround using this method is now built in to Zeroconf; on iOS version 14.5 and greater, when ZeroconfResolver.ResolveAsync() or ZeroconfResolver.BrowseAsync() functions are called, this workaround code is executed.

Setup

This following actions are required for this workaround:

  1. In your Xamarin.iOS project, modify Info.plist to include something like the following:
  <key>NSLocalNetworkUsageDescription</key>
  <string>Looking for local mDNS/Bonjour services</string>
  <key>NSBonjourServices</key>
  <array>
    <string>_audioplayer-discovery._tcp</string>
    <string>_http._tcp</string>
    <string>_printer._tcp</string>
    <string>_apple-mobdev2._tcp</string>
  </array>

The effect of the above: the first time your app runs, iOS will prompt the user for permission to allow mDNS queries from your app; it will display the value of the key NSLocalNetworkUsageDescription to the user.

For the key NSBonjourServices, its array of values is the list of mDNS services that your app needs in order to run properly; iOS will only allow mDNS information from those listed services to reach your app. Note that the domain (usually ".local.") is not specified in Info.plist.

Both the NSLocalNetworkUsageDescription and NSBonjourServices key values should be changed to what is required for your application.

  1. Possible modification of BrowseAsync() calling code, if applicable

Calling BrowseAsync() followed by ResolveAsync() is essentially doing the same work twice: BrowseAsync is simulated using ResolveAsync() with the list of NSBonjourServices from Info.plist. When you can modify the code, calling only ResolveAsync() only will provide you all the information you need in half the time.

The list of services from Info.plist are obtainable from ZeroconfResolver.GetiOSInfoPlistServices(), and a platform-independent way to know if the workaround is enabled is the property ZeroconfResolver.IsiOSWorkaroundEnabled.

If you have to deal with custom mDNS domains, ZeroconfResolver.GetiOSDomains() will search the network for domains and return their names. The chosen domain may then be used as a parameter to ZeroconfResolver.GetiOSInfoPlistServices(domain). See Apple's documentation

Example browse and resolve code:

IReadOnlyList<IZeroconfHost> responses = null;

IReadOnlyList<string> domains;
if (ZeroconfResolver.IsiOSWorkaroundEnabled)
{
    // Demonstrates how using ZeroconfResolver.GetiOSInfoPlistServices() is much faster than ZeroconfResolver.BrowseDomainsAsync()
    //
    // In real life, you'd only query the domains if you were planning on presenting the user with a choice of domains to browse,
    //  or the app knows in advance there will be a choice and what the domain names would be
    //
    // This code assumes there will only be one domain returned ("local.") In general, if you don't have a requirement to handle domains,
    //  just call GetiOSInfoPlistServices() with zero arguments

    var iosDomains = await ZeroconfResolver.GetiOSDomains();
    string selectedDomain = (iosDomains.Count > 0) ? iosDomains[0] : null;

    domains = ZeroconfResolver.GetiOSInfoPlistServices(selectedDomain);
}
else
{
    var browseDomains = await ZeroconfResolver.BrowseDomainsAsync();
    domains = browseDomains.Select(g => g.Key).ToList();
}

responses = await ZeroconfResolver.ResolveAsync(domains);

Unimplemented features in the workaround

ListenForAnnouncementsAsync()

ResolverListener()

Implementation Details

The callback functions are based on a simple-minded implementation: they will be called only after each ScanTime interval has expired for each distinct protocol/mDNS service.

The more protocols/mDNS services you resolve, the longer it takes the library to return: minimumTotalDelayTime = (nServices * ScanTime).

Known bugs

There is no propagation of errors (NetService_ResolveFailure, Browser_NotSearched) from the iOS API to ZeroconfSwitch. If any of these errors occur, you simply get nothing and like it.

Credits

This library was made possible through the efforts of the following projects:

zeroconf's People

Contributors

clairernovotny avatar dependabot-preview[bot] avatar dependabot[bot] avatar ghuntley avatar joj avatar jorgensigvardsson avatar kakone avatar kobush avatar lakritzator avatar marcus-l avatar queequac avatar saldoukhov avatar sparksteam avatar spudwebb avatar thomasniederreiner-aracom avatar yanntremblay96 avatar zone117x 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  avatar  avatar  avatar

zeroconf's Issues

Fatal signal 11 (SIGSEGV) when build for release

Using Zeroconf in a Xamarin project in Andriod. Works fine when building for debug. However when building for release (and using the "Link SDK Assemblies Only" linker option) Zeroconf gets a SIGSEGV soon after being fired up (looks like during SetSocketOption call). Stacktrace:

[mono-rt] Stacktrace:
[mono-rt]
[mono-rt] at <0xffffffff>
[mono-rt] at (wrapper managed-to-native) System.Net.Sockets.Socket.SetSocketOption_internal (intptr,System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,object,byte[],int,int&) <0xffffffff>
[mono-rt] at System.Net.Sockets.Socket.SetSocketOption (System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,object) <0x0017b>
[mono-rt] at Zeroconf.NetworkInterface/d__1.MoveNext () <0x004bb>
[mono-rt] at System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start<Zeroconf.NetworkInterface/d__1> (Zeroconf.NetworkInterface/d__1&) <0x0004b>
[mono-rt] at Zeroconf.NetworkInterface.NetworkRequestAsync (byte[],System.TimeSpan,int,int,System.Action`2<string, byte[]>,System.Threading.CancellationToken) <0x00197>
[mono-rt] at Zeroconf.ZeroconfResolver/d__1.MoveNext () <0x004df>
[mono-rt] at (wrapper unbox) Zeroconf.ZeroconfResolver/d__1.MoveNext () <0xffffffff>
[mono-rt] at System.Threading.Tasks.SynchronizationContextContinuation.m__0 (object) <0x0003f>
[mono-rt] at Android.App.SyncContext/c__AnonStorey0.<>m__0 () <0x00027>
[mono-rt] at Java.Lang.Thread/RunnableImplementor.Run () <0x0003f>
[mono-rt] at Java.Lang.IRunnableInvoker.n_Run (intptr,intptr) <0x0003b>
[mono-rt] at (wrapper dynamic-method) object.d9fe47de-8f69-4aab-be74-e4bec4c1f295 (intptr,intptr) <0x0003b>
[mono-rt] at (wrapper native-to-managed) object.d9fe47de-8f69-4aab-be74-e4bec4c1f295 (intptr,intptr) <0xffffffff>
[mono-rt]
[mono-rt] =================================================================
[mono-rt] Got a SIGSEGV while executing native code. This usually indicates
[mono-rt] a fatal error in the mono runtime or one of the native libraries
[mono-rt] used by your application.
[mono-rt] =================================================================
[mono-rt]
[libc] Fatal signal 11 (SIGSEGV) at 0x0000000c (code=1), thread 15082 (kit.Android.dev)

Is there a known way to avoid this problem?

System.UnauthorizedAccessException

I just loaded this up in a Universal Windows Application (C#) which I'm attempting to learn right now. When copy in the sample line of code to search for devices I get the message:

An exception of type 'System.UnauthorizedAccessException' occurred in mscorlib.ni.dll but was not handled in user code

WinRT information: At least one of either InternetClientServer or PrivateNetworkClientServer capabilities is required to listen for or receive traffic

Additional information: Access is denied.

I'm using your sample (I should have a printer that is discoverable):
public async Task ProbeForNetworkPrinters()
{
IReadOnlyList results = await
ZeroconfResolver.ResolveAsync("_printer._tcp.local.");
}

UTF-8 in the DisplayName isn't processed correctly

This is a nice project, and seems to work quite well.

Here a little bug I noticed:
I have an Airplay device, Apple TV 3, which is called "Apple TV (Bรผro)".
When I discover the service, the DisplayName is "Appleร‚ย TV (Bรƒยผro) (2)"
I don't know what is behind "Apple", but it's definitively clear that the "รผ" (u-umlaut) is not processed correctly.

As far as I could find in the documentation, this should not cause any problem.
Just in case I tried the first Windows App Store app I could find to test this, this was "AirPlayTo Audio", and there it was displayed correctly.

I guess, didn't look in the code yet, everything is processed as ascii while UTF-8 should be used.

P.S.
Although I really like reactive extensions, I wonder how much of it you are really using.
Your dll is ~39KB, the reactive dll's are 828KB (of which the System.Reactive.Linq.dll is 692KB!!)
Surely in real life one MB more or less is not so dramatic, if I compare the size of the Greenshot installer (about 1.5MB) to the size this will grow when I add Zeroconf functions: it will almost be 2x the size. Just something to think about, as soon as there are good reasons for it I'm not complaining.

Thanks for the neat project!

Resolve() on WIFI networks has varying results.

We are using Zeroconf to do service discovery of printer / scanner type devices. I find that on LAN networks, the results returned by Resolve() are very consistent, and usually return within a few seconds of issuing the Resolve(). However, on WIFI networks, especially on Android/iOS, I am finding quite a bit of variance in what is found. Sometimes I get a few devices, sometimes none, sometime lots. And, it doesn't seem to matter what i set the discoveryTime value at. If it doesn't find them in the first few seconds, longer discoveryTimes have no relevance. As such, I find that I've had to implement a "continuous discovery" mechanism by which I just submit Resolve() requests every few seconds, and then aggregate the results and throw out duplicates. I don't think this is how it should work, but perhaps this is what was intended?

Thanks
Jeremy

Exception when doing ResolveAsync() on iOS connected to WIFI direct Access Point device

Hi,

As you are aware, iOS doesn't support true WIFI direct Peer 2 Peer. But WIFI direct devices can still support an ad-hoc access point mode by which iOS can connect. We are using the latest ZeroConf package on Xamarin.iOS to attempt to do Bonjour discovery over such a connection, and we are getting a exception of the following type thrown:

InvalidOperationException: Bind has already been called for this socket

ResolveAsync() does succeed in this same scenario using Xamarin.Android.

Any thoughts on this? I've attached the full exception callstack that we see.

Thanks
Jeremy
crash stack.txt

No .NET 4.5 support in NuGet package

I tried a ZeroConf search in the nuget library in a solution that just has projects targeting .NET 4.5 and the results came up empty.

I went the manual route and tried "Install-Package ZeroConf" from the console and got the following:

Install-Package : Could not install package 'Zeroconf 2.3.3'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.0', but the
package does not contain any assembly references or content

Is there another route to get the .NET 4.5 component outside of compiling our own? Or is this an issue you are able to resolve by rebuilding the nuget package with a .NET 4.5 target (I admit i'm ignorant to the ways of nuget package building)?

Confused about the API

Hi, I'm looking to create my own Bonjour service advertisement, and this looks like the general tool to do that (though I'm new to network dev and I might be lost). I see the docs on the front page showing how to enumerate the available Bonjour services (and it worked) but I guess I'm looking for a more extensive documentation that includes advertisement.
I tried Mono.Zeroconf before but ran into problems, and this project looks like a good alternative since you're actively supporting it. :)

Discovery not working on Windows 8.1

Hi,

I'm developping an application on windows phone 8.1 and windows 8.1
I'm using Zerconf to discover a device. I installed it with nuget on each project (PCL, windows phone and windows).

The discover method is shared thrue a Portable Class Library.
Everything work fine on Windows phone but nothing is discovered on windows.

Here is the code :

IReadOnlyList hosts = await ZeroconfResolver.ResolveAsync("myservice");
foreach (IZeroconfHost host in hosts)
{
foreach (IService service in host.Services.Values)
{
System.Diagnostics.Debug.WriteLine(string.Format("ID : {0}, IPAddress : {1}, Name : {2}, Port : {3}", host.Id, host.IPAddress, host.DisplayName, service.Port));
}
}

There is no error, no exception, just an empty hosts.

Do you have an idea why ?
How can I diagnose the problem ?

Thank you

Errors on Windows Phone 10 Preview

I realize that Windows Phone is pre-release software but I thought I would give a heads-up. The problem does not occur on a Lumia 1520 running Windows Phone 8.1.

When running the ZeroconfTest.WP on a Lumia 635 running Windows 10 Preview, I get numerous errors (see below). It seems that these are on a call to BrowseDomainsAsync or ResolveAsync.

A first chance exception of type 'System.Exception' occurred in mscorlib.ni.dll
WinRT information: Only one usage of each socket address (protocol/network address/port) is normally permitted.

A first chance exception of type 'System.Exception' occurred in mscorlib.ni.dll
WinRT information: Only one usage of each socket address (protocol/network address/port) is normally permitted.

Exception trying to Bind:System.Exception: Only one usage of each socket address (protocol/network address/port) is normally permitted.

Only one usage of each socket address (protocol/network address/port) is normally permitted.

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
at Zeroconf.NetworkInterface.d__b.MoveNext()
--- 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 System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
at Zeroconf.NetworkInterface.d__4.MoveNext()
Retrying in 2000 ms
A first chance exception of type 'System.Exception' occurred in mscorlib.ni.dll
WinRT information: Only one usage of each socket address (protocol/network address/port) is normally permitted.

Discovery through hotspot

I'm having trouble discovering zeroconf services that hosts connected to the iPad using its hotspot are serving.

Here's the scenario:

  1. iPad is in hotspot mode
  2. device with zeroconf server is connected to the iPad personal hotspot using wifi (to simplify testing i've been using xamarin's build host as the zeroconf server since our own host requires a separate piece of hardware)
  3. a call is made to BrowseDomainsAsync but always shows up empty

I tested the same code with both the iPad and the device connected to the same wifi network and had no trouble discovering the service being offered, but if I go into hotspot mode it doesn't appear to be broadcasting the request to the internal wifi network, just the cellular network, so my app never finds the hosted service.

Any clue on this? Would you expect this to work? I briefly read through the code and it appears you're broadcasting such that it should go to every network. Maybe a modification can be made (on my end if necessary) to allow me to specify the netmask or some portion of the IP range to broadcast to (e.g. 172.20.10.*)?

Multiple network cards

Please add support for multiple network interfaces. If there are two or more network adapters then the network card which receive the broadcast seems to be randomly. The cause is that subnet mask does not match the broadcast interface.

You can test it if you add a "Microsoft KM-TEST Loopback Adapter" (Win 10) or "Microsoft Loopback Adapter" (older Win). On my system ever the loopback adpater receive the broadcast.

In our Java implementation we iterate over all network interfaces, filter the adapter with one or more IP addresses and send a broadcast to the adapter to the Ip4/Ip6 broadcast address depending of the type of the address. I expect this should also work in the .NET world.

Errror with demo code

Getting an error with both of your examples. Running on Windows VS2013.

Cannot access a disposed object.
Object name: 'System.Net.Sockets.UdpClient'.

Thanks.

Add version to assemblies

Currently the assemblies do all lack a proper version information.
It would be really great if the zeroconf assemblies could be versioned (in sync with the nuget packages).

Personally I do have references to open source components, their version, license and stuff in the "about" section. And it would be much easier if I could simply use the assembly version their instead of adjusting the version each time manually. :)

Since RT and Portable do already have a shared assembly info, I added the (upcoming 2.7) version there and added a link to this file for the UWP project also.
PR follows, would be great, Oren, if you could keep that version incremented along with your public nuget releases.

By the way, any chance for the 2.7 nuget package soon? I am waiting for weeks to get the UWP assembly through nuget, since the RT variant is useless under Windows 10. Would really appreciate if you could kick it to nuget.

Thanks, Roland

What is README.md talking about?

From README.md:

The core logic is implemented as a PCL, but due to networking APIs being platform-specific, a platform-specific helper library is required. Just make sure that you also install the NuGet to your main app and you'll be all set.

What is it talking about?

I know PCL stands for "Portable Class Library", but I don't think everybody knows it.

And what "platform-specific helper library"? Can you give an example? Do you mean something like Apple's Bonjour SDK for Windows, if I want to use this Zeroconf in a .NET 4.5 application on Windows 8.1?

Can I use Zeroconf for Mac desktop App?

I've added Zeroconf package in Xamarin's package manager and build my app without error. But it does not work. I'd like to know if your Zeroconf works on Mac and Mono or not.

screen shot 2016-07-03 at 10 32 56

version

Zeroconf 2.7.1

environment

Xamarin Studio Community Version 6.0.1 (build 9)
Runtime: Mono 4.4.1 (mono-4.4.0-branch-c7sr0/4747417) (64-bit)
Xamarin.Mac Version: 2.8.1.4 (Xamarin Studio Community)
Mac OS X 10.11.5 Darwin iMac.local 15.5.0 Darwin Kernel Version 15.5.0

source code

using Zeroconf;
namespace Hello_Mac {
public partial class ViewController : NSViewController {
public async override void ViewDidLoad() {
base.ViewDidLoad();
IReadOnlyList results = await
ZeroconfResolver.ResolveAsync("_irkit._tcp.local");
}
}
}

error

System.TypeInitializationException: The type initializer for 'Zeroconf.ZeroconfResolver' threw an exception. ---> System.NotSupportedException: This PCL assembly must not be used at runtime. Make sure to add the Zeroconf Nuget reference to your main project.
at Zeroconf.ZeroconfResolver.LoadPlatformNetworkInterface () [0x00000] in :0
at Zeroconf.ZeroconfResolver..cctor () [0x0000a] in :0
--- End of inner exception stack trace ---
at Hello_Mac.ViewController+c__async0.MoveNext () [0x00042] in /Users/hanyazou/github/Hello_Xamarin/Hello_Mac/ViewController.cs:26
at --- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Users/builder/data/lanes/3412/3cf8aaed/source/maccore/_mac-build/Library/Frameworks/Xamarin.Mac.framework/Versions/git/src/mono/external/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:143
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.m__0 (System.Object state) [0x00000] in /Users/builder/data/lanes/3412/3cf8aaed/source/maccore/_mac-build/Library/Frameworks/Xamarin.Mac.framework/Versions/git/src/mono/external/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:1018
at AppKit.AppKitSynchronizationContext+c__AnonStorey0.<>m__0 () [0x0000c] in /Users/builder/data/lanes/3412/3cf8aaed/source/maccore/src/AppKit/AppKitSynchronizationContext.cs:17
at Foundation.NSAsyncActionDispatcher.Apply () [0x00008] in /Users/builder/data/lanes/3412/3cf8aaed/source/maccore/src/Foundation/NSAction.cs:163
at at (wrapper managed-to-native) AppKit.NSApplication:NSApplicationMain (int,string[])
at AppKit.NSApplication.Main (System.String[] args) [0x00041] in /Users/builder/data/lanes/3412/3cf8aaed/source/maccore/src/AppKit/NSApplication.cs:94
at Hello_Mac.MainClass.Main (System.String[] args) [0x00007] in /Users/hanyazou/github/Hello_Xamarin/Hello_Mac/Main.cs:10

Query SRV records

Does your library support querying DNS for SRV (Service) records? I am looking to somehow get access to DNSServiceQueryRecord on iOS. Thanks!

Discovery over multiple network adapters

I'm working on a project were the goal is to discover zeroconf services over both DHCP enabled networks as well as auto-assigned IP address networks. The following scenarios can occur:

  1. The user plugs a device with Zeroconf services directly in the ethernet port of his laptop (while the laptops WIFI is enabled)
  2. The user plugs a device with Zeroconf services in a DHCP enabled network, while trying to discover it using his laptop which is on the same network

Scenario 2 seems to be working properly since the discovery nicely picks the adapter which is connected to the DHCP network as the 'best' adapter. In scenario 1 however the device is not discovered since the wifi adapter is chosen as the 'best' adapter instead of the ethernet adapter.

I have already resolved this issue by cloning your code and extending it by broadcasting over all (active and broadcastable) adapters. I'm unable however to verify the workings of the new code on other platforms such as Xamarin/Android/IOS. I have verified the workings on the windows (.NET45) platform.

I have included the modified code (for the NetworkInterface class) below, if you'd like I can create a branch/fork with the updated code so you can check whether or not you would like to include it in your package.

namespace Zeroconf
{
    internal class NetworkInterface : INetworkInterface
    {
#if ANDROID
        private readonly WifiManager wifi;

        public NetworkInterface()
        {
            var context = Application.Context.ApplicationContext;
            wifi = (WifiManager)context.GetSystemService(Context.WifiService);
        }
#endif

        public async Task NetworkRequestAsync(byte[] requestBytes,
                                              TimeSpan scanTime,
                                              int retries,
                                              int retryDelayMilliseconds,
                                              Action<string, byte[]> onResponse,
                                              CancellationToken cancellationToken)
        {
            var tasks = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()
                .Select(inter => 
                    NetworkRequestAsync(requestBytes, scanTime, retries, retryDelayMilliseconds, onResponse, inter, cancellationToken))
                    .ToList();

            await Task.WhenAll(tasks);
        }


        private async Task NetworkRequestAsync(byte[] requestBytes,
                                              TimeSpan scanTime,
                                              int retries,
                                              int retryDelayMilliseconds,
                                              Action<string, byte[]> onResponse,
                                              System.Net.NetworkInformation.NetworkInterface adapter,
                                              CancellationToken cancellationToken)
        {
            // http://stackoverflow.com/questions/2192548/specifying-what-network-interface-an-udp-multicast-should-go-to-in-net
            if (!adapter.GetIPProperties().MulticastAddresses.Any())
                return; // most of VPN adapters will be skipped

            if (!adapter.SupportsMulticast)
                return; // multicast is meaningless for this type of connection

            if (OperationalStatus.Up != adapter.OperationalStatus)
                return; // this adapter is off or not connected

            var p = adapter.GetIPProperties().GetIPv4Properties();
            if (null == p)
                return; // IPv4 is not configured on this adapter


            using (var client = new UdpClient())
            {
                for (var i = 0; i < retries; i++)
                {
#if ANDROID
                    var mlock = wifi.CreateMulticastLock("Zeroconf lock");
#endif
                    try
                    {
#if ANDROID
                        mlock.Acquire();
#endif

                        var localEp = new IPEndPoint(IPAddress.Any, 5353);

#if XAMARIN
                        const int ifaceIndex = 0;
#else
                        var ifaceIndex = p.Index;
#endif

                        client.Client.SetSocketOption(SocketOptionLevel.IP,
                                                      SocketOptionName.MulticastInterface,
                                                      IPAddress.HostToNetworkOrder(ifaceIndex));



                        client.ExclusiveAddressUse = false;
                        client.Client.SetSocketOption(SocketOptionLevel.Socket,
                                                      SocketOptionName.ReuseAddress,
                                                      true);
                        client.Client.SetSocketOption(SocketOptionLevel.Socket,
                                                      SocketOptionName.ReceiveTimeout,
                                                      scanTime.Milliseconds);
                        client.ExclusiveAddressUse = false;

                        client.Client.Bind(localEp);

                        var multicastAddress = IPAddress.Parse("224.0.0.251");

                        var multOpt = new MulticastOption(multicastAddress, ifaceIndex);
                        client.Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, multOpt);


                        Debug.WriteLine("Bound to multicast address");

                        // Start a receive loop
                        var shouldCancel = false;
                        var recTask = Task.Run(async
                                               () =>
                        {
                            try
                            {
                                while (!shouldCancel)
                                {
                                    var res = await client.ReceiveAsync()
                                                          .ConfigureAwait(false);
                                    onResponse(res.RemoteEndPoint.Address.ToString(), res.Buffer);
                                }
                            }
                            catch (ObjectDisposedException)
                            {
                            }
                        }, cancellationToken);

                        var broadcastEp = new IPEndPoint(IPAddress.Parse("224.0.0.251"), 5353);


                        await client.SendAsync(requestBytes, requestBytes.Length, broadcastEp)
                                    .ConfigureAwait(false);
                        Debug.WriteLine("Sent mDNS query");


                        // wait for responses
                        await Task.Delay(scanTime, cancellationToken)
                                  .ConfigureAwait(false);
                        shouldCancel = true;
                        client.Close();
                        Debug.WriteLine("Done Scanning");


                        await recTask.ConfigureAwait(false);

                        return;
                    }
                    catch (Exception e)
                    {
                        Debug.WriteLine("Execption: ", e);
                        if (i + 1 >= retries) // last one, pass underlying out
                            throw;
                    }
                    finally
                    {
#if ANDROID
                        mlock.Release();
#endif
                    }

                    await Task.Delay(retryDelayMilliseconds, cancellationToken).ConfigureAwait(false);
                }
            }
        }
    }
}

Explicit UWP support

Currently Zeroconf.RT is intended to serve as helper library for Windows Phone 8.1, Windows Store apps as well as UWP apps.

But it has to be noted that targeting the 8.1 platforms has certain limitations that make Zeroconf quite useless. To be precise, the former RT platform does not allow re-using ports. Whenever some other application did already listen to mDNS messages, Windows threw an exception "Only one usage of each socket address (protocol/network address/port) is normally permitted.".
In this case Zeroconf.RT code falls back to a datagram socket without specified port - this is where the trouble actually begins. When no port is specified, you may join a multicast group, but you won't receive anything. While the output stream has port 5353 (since it is specified separately when getting the stream) and the query will be sent out correctly, you will not receive responses with Zeroconf (but with Wireshark you can see them).

As a result I often found no services with Windows Phone 8.1, and one of my apps falls back to UPnP discovery then (because the devices I am searching for can be found with both).
With Windows 10 this seems to be even more critical. To be honest, I never found any service with Zeroconf anymore, since all my phones and desktops do have port 5353 already in use. As mentioned above, the fallback is quite useless, since I sends out the request but won't receive anything without given port.

Fortunately the UWP platform evolves. Starting with Windows 10 it is possible to set a socket's control option to multicast only (socket.Control.MulticastOnly = true). When restricting a socket to multicast, windows no longer prevents the re-use of a port already in use.

Since this can hardly be integrated into the RT helper library, I created a new one for UWP which does that trick and implements also ListenForAnnouncementsAsync method.

A pull request with helper library and test application is following. Would be great if this could become part of the official code base and available along with the nuget package. :)

Extending the Interface

In PR #25, I've extended the interface a little more to provide a scan-in-progress status, throw an exception if a start scan is attempted while scanning is in progress, added a mechanism to know when scanning is complete via the callback, and also tested the Cancel scan mechanism. Please consider for incorporation into the main. Thanks.

Failed to run on Nougat android phones

This might be beyond your control, but just wanted to let you know.

On Android 7 phones, the underlying way that you can obtain information on network adapters has changed so a number of properties (such as SupportsMulticast) always returns false. We are running on top of Xamarin and we see it in the Output as

11-14 15:04:44.665 W/_olufsen.OneApp(11974): type=1400 audit(0.0:5963): avc: denied { getattr } for path="/sys/class/net/r_rmnet_data6" dev="sysfs" ino=27642 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:sysfs:s0 tclass=lnk_file permissive=0
11-14 15:04:44.665 W/_olufsen.OneApp(11974): type=1400 audit(0.0:5964): avc: denied { getattr } for path="/sys/devices/virtual/net/r_rmnet_data5/flags" dev="sysfs" ino=27593 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:sysfs:s0 tclass=file permissive=0
11-14 15:04:44.665 W/_olufsen.OneApp(11974): type=1400 audit(0.0:5965): avc: denied { getattr } for path="/sys/class/net/r_rmnet_data5" dev="sysfs" ino=27576 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:sysfs:s0 tclass=lnk_file permissive=0

From a bit of digging, this seems to be the root issue: https://bugzilla.xamarin.com/show_bug.cgi?id=44296

Xamarin/Mono has been updated with a fix in their current branch but as far as I can tell it has not been added to the Stable version. We ran into this issue and after some digging got things working by skipping the checks for SupportsMulticast and OperationalStatus (which are false and Unkown respectively) so we effectively scan more network adapters

Not sure if this warrants any action on your part, since at least Xamarin seems to be aware of this and is fixing it at some point.

Reactive enforces en-US locale

So far I have been using Zeroconf up to version 2.4.0.
But recently I gave the latest version 2.5.0 a try, realizing that its usage of Reactive enforces the en-US locale. (See first two lines from command line below.)

1>MakePRI : warning 0xdef00522: Resources found for language(s) 'en-us' but no resources found for default language(s): 'de-DE'. Change the default language or qualify resources with the default language. http://go.microsoft.com/fwlink/?LinkId=231899
1>MakePRI : warning 0xdef01051: No default or neutral resource given for 'System.Reactive.Strings_Linq/CANT_ADVANCE_WHILE_RUNNING'. The application may throw an exception for certain user configurations when retrieving the resources.
...

For Windows 10 apps this leads even to an additional "supported language" entry for English, even if the app does NOT. This demands to create an additional package description in English for the store. :/

For the moment I will keep my hands off version 2.5.0, as long as it cannot be used in a really language neutrale manner.

STOWED_EXCEPTION_System.Exception

Hello there,

Some users of my application complains that it does not work. They say that the device I want to discover is not discovered.
I am not able to reproduce the problem.

But, the top one of exceptions generated by this application is :

STOWED_EXCEPTION_System.Exception_80072744_Zeroconf.dll!Zeroconf.NetworkInterface+__c__DisplayClass0_0._NetworkRequestAsync_b__0

Here is the stack trace :
Frame Image Function Offset
0 Windows_ni Windows.Networking.Sockets.DatagramSocketMessageReceivedEventArgs.GetDataReader 0x1
1 Zeroconf_ni Zeroconf.NetworkInterface+__c__DisplayClass0_0._NetworkRequestAsync_b__0 0x1A

It is a Windows Phone 8.1 app.
I have no other informations.
Can you help me please ?

Thank you.
Alek

TXT Records with a BAD length cause "Out of Memory" Exception in NetFx library

Hi

I've been tracking down out of memory exceptions when using your library. It turns out they are due to a bad TXT record RDLENGTH field from a device on my network (it is serialising the ushort in Little Endian format which gives us a length of 11008 instead of 43.

Aside from the root of the cause being the bad device, the ReadByte() and ReadString() methods in RecordReader.cs continue to create StringBuilders due to the code in RecordTXT constructor

public RecordTXT(RecordReader rr, int Length)
{
    int pos = rr.Position; // This is initially 147 in my case, with m_data[190]
TXT = new List<string>();
    while ((rr.Position - pos) < Length)
    TXT.Add(rr.ReadString());
}

(rr.Position - pos) == 190 - 147 == 43

The while loop test equals 43 and this is never more than 11008, which results in Out of Memory.

Please let us know if you would like me to do any further testing? I can also work on a fix, but my testing would be limited to the .NET4.5 framework only.

Cheers

Dave

Resolver returning incorrect devices

When calling the ZeroconfResolver.ResolveAsync method and specifying "_googlecast._tcp.local." as the protocol I will intermittently see results that are not Chromecast devices. Sometimes AppleTV or other Apple devices will show up in the results.

ZeroconfResolver.ResolveContinuous causes System.NullReferenceException

Hi, I am using the ZeroconfResolver.ResolveContinuous() Method to watch for new camera devices in my local network. Pretty randomly, I am getting a System.NullReferenceException. Am I doing something wrong? I am not very experienced with Rx, it is my first try :)

The Code is running on a windows 7 machine. The Frameworkversion is 4.61.

My Code:

        public VirbCameraProvider()
        {
            Cameras = new ObservableCollection<Virb>();
            m_Disposables = new List<IDisposable>();
            m_Disposables.Add(ZeroconfResolver.ResolveContinuous("_garmin-virb._tcp.local.")
                .ObserveOn(SynchronizationContext.Current)
                .Subscribe(HostFound));
        }
...
        private void HostFound(IZeroconfHost host)
        {
            if (!host.Services.ContainsKey("_garmin-virb._tcp.local.") || host.Id != host.IPAddress) return;
            if (Cameras.Any(v => v.Ip == host.IPAddress || v.Name == host.DisplayName))
            {
                var ipChangedVirb = Cameras.SingleOrDefault(v => v.Name == host.DisplayName && v.Ip != host.IPAddress);
                if (ipChangedVirb == null)
                    return;
                RemoveCamera(ipChangedVirb);
            }
            var virb = new Virb(host.IPAddress, host.DisplayName);
            virb.StateNull
                .ObserveOn(SynchronizationContext.Current)
                .Subscribe(count =>
            {
                if (count > 4)
                    RemoveCamera(virb);
            });
            Cameras.Add(virb);
        }

Stack Trace:

System.NullReferenceException was unhandled
  HResult=-2147467261
  Message=Object reference not set to an instance of an object.
  Source=Zeroconf
  StackTrace:
       at Zeroconf.NetworkInterface.<NetworkRequestAsync>d__1.MoveNext() in C:\projects\zeroconf\Zeroconf.DotNetCore\NetworkInterface.cs:line 159
    --- 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 Zeroconf.NetworkInterface.<NetworkRequestAsync>d__0.MoveNext() in C:\projects\zeroconf\Zeroconf.DotNetCore\NetworkInterface.cs:line 33
    --- 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 Zeroconf.ZeroconfResolver.<ResolveInternal>d__4.MoveNext() in C:\projects\zeroconf\Zeroconf.Shared\ZeroconfResolver.cs:line 75
    --- 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 Zeroconf.ZeroconfResolver.<ResolveAsync>d__15.MoveNext() in C:\projects\zeroconf\Zeroconf.Shared\ZeroconfResolver.Async.cs:line 69
    --- 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 Zeroconf.ZeroconfResolver.<>c__DisplayClass8_0.<<Resolve>b__0>d.MoveNext() in C:\projects\zeroconf\Zeroconf.Shared\ZeroconfResolver.Observable.cs:line 56
    --- End of stack trace from previous location where exception was thrown ---
       at System.Reactive.PlatformServices.DefaultExceptionServices.Rethrow(Exception exception)
       at System.Reactive.Stubs.<.cctor>b__1(Exception ex)
       at System.Reactive.AnonymousSafeObserver`1.OnError(Exception error)
       at System.Reactive.Concurrency.ObserveOn`1.ObserveOnSink.OnErrorPosted(Object error)
       at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
       at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
       at System.Windows.Threading.DispatcherOperation.InvokeImpl()
       at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
       at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Windows.Threading.DispatcherOperation.Invoke()
       at System.Windows.Threading.Dispatcher.ProcessQueue()
       at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
       at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
       at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
       at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
       at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
       at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
       at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
       at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
       at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
       at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
       at System.Windows.Application.RunDispatcher(Object ignore)
       at System.Windows.Application.RunInternal(Window window)
       at System.Windows.Application.Run(Window window)
       at System.Windows.Application.Run()
       at PavementPicker.App.Main() in C:\dev\euk\PavementPicker\PavementPicker\obj\Debug\App.g.cs:line 0
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

Can not add nuget package to PCL project

Hi,
I tried Zeroconf with usual Windows Forms project, and it works perfectly. Thank you for your work.

Now I'm trying to add Zeroconf to my PCL library (v4.5, Profile111). The first problem I run into was the same as described here (System.Runtime.InteropServices.RuntimeInformation installation failed)

I've applied project.json to my PCL libary (guide) and now instalation of Zeroconf is OK but buid is failed with

'C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Common.CurrentVersion.targets'
(1820,5): warning MSB3274: The primary reference "...\.nuget\packages\Zeroconf\2.8.0\lib\netstandard1.0\Zeroconf.dll" could not be resolved because it was built against the ".NETPortable,Version=v5.0" framework. This is a higher version than the currently targeted framework ".NETPortable,Version=v4.5,Profile=Profile111".

project.json:

{
  "dependencies": {
    "Zeroconf": "2.8.0"
  },
  "frameworks": {
    ".NETPortable,Version=v4.5,Profile=Profile111": {}
  },
  "supports": {}
}

Please, help me to add Zeroconf to my project.

DisplayName on Chromecast is incorrect

This had been previously working but I noticed today that The DisplayName for Chromecast based devices appear to be a combination of the "md" and "id" properties. For instance, the result of the ResolveAsync method is returning a Chromecast device with a name following the pattern below:

md-id

While investigating the service properties in the debugger it appears that the "fn" property should be used for the DisplayName.

The Reactive/Observable feature should be an addon nuget package

We don't need the feature and avoid including unused dependencies in our product, so we removed the System.Reactive package dependency and ZeroconfResolver.Observable.cs file.

PingmanTools@1280a0d

It seems like most users of the Zeroconf lib probably don't use the feature. I think it should be pulled out into its own project and published as an addon nuget package.

[monodroid-netlink] Failed to bind to the netlink socket. Address already in use

I'm getting this message when trying to use Zeroconf in an Android app written with xamarin.

[monodroid-netlink] Failed to bind to the netlink socket. Address already in use

The example project works fine. What could be causing this? I am adding the Zeroconf nuget package to my android project which I thought is all I need.

Hosting on specific Network Adapter

Having an issue where Bonjour chooses to host the service on whatever Network Adapter it wants to. In cases where we're running VMs the service will all of a sudden end up on that Network Adapter when we want it on a different one. Wondering if there's a way to specify which one we'd like to host it from, or if this could be a feature implementation.

Call to ZerconfResolver.ResolveAsync never returns

I'm trying to use Zerconf for my first time in a Xamarin.Forms project for iOS and Android, but the sample methods provided in the ReadMe file do not seem to work. The call goes out, but never returns. I've tried providing nothing but the protocol, and also tried providing all parameters, but nothing ever comes back.

I'm trying this with just a largely empty project... One button to try the printer lookup.

Perhaps I am neglecting some sort of setup not mentioned in the ReadMe? Are there any additional sample implementations you could point me to, if this sounds like a PEBKAC issue?

Thanks very much!

Core CLR

Hi, Is it possible to add support for Core CLR platform, I'd like to use the library within UWP application and ASP.NET 5 WebAPI project (Core CLR)

Error in Service Enumeration

Hi,

I just tried Zeroconf for the first time, referenced it in an empty .Net 4.5 Forms project via Nuget. The only function I'm calling is the "EnumerateAllServicesFromAllHosts()" from within the Form's constructor.

I'm getting pretty random "A first chance exception of type 'System.ObjectDisposedException' occurred in mscorlib.dll" error messages. I'm on a pretty big network with lots of Bonjour services, Zeroconf is able to find some but by far not all. Each time I start the program, the number of error messages is random, between 3 to 6. It seems that the number of discovered services is higher when I have less error messages.

Michael

[Feature Request] - Registering a service on Xamarin.Android and/or Xamarin.iOS

Hi Oren,

I am working on a project where I need to do peer to peer communications across Android and iOS, and I found this library.
This seems perfect for what I want to do, but would need to add the ability to register new services as well as discovering them.

Is it possible to add such a feature? I am happy to help out with the development, but I do not have much experience in this space, so I would need some guidance :)

Thanks heaps for the great effort
Cheers
Has

Service Publishing

This package only supports enumeration of services published via mDNS.

If no service publishing is supported, stating this in README would save developers
looking to publish services some time.

Thanks.

iOS invalid operation exception when doing Resolve() with both cell data and WIFI turned on.

We are seeing an exception being thrown in ZeroConf 2.7.1 on iOS when we try to do a Resolve() when connected to both a WIFI network and have cell data enabled. This doesn't seem to happen on all devices, and unfortunately it doesn't reproduce on my personal device that I am debugging on. I captured an exception trace of this from another device, and here's what we see:

InvalidOperationException: Bind has already been called for this socket
at System.Net.Sockets.Socket.set_ExclusiveAddressUse (Boolean value) <0x10108f570 + 0x00094> in :0
at System.Net.Sockets.UdpClient.set_ExclusiveAddressUse (Boolean value) <0x1010a1740 + 0x00027> in :0
at Zeroconf.NetworkInterface+d__1.MoveNext () <0x101d58b40 + 0x004ef> in :0
--- End of stack trace from previous location where exception was thrown ---

On this particular device, if we then disable cell data, everything works normally. I know this is not much to go off of, I had hoped to reproduce this with a debug version of ZeroConf to give more details, and will continue to try to do so. We don't see this on Android at all.

Thanks
Jeremy

Try to discover service in openhab multicast functionality failed

Hello,

i try to discover the openhabe service with zeroconf on a windows phone 8.1. But the ResolvAsync gives me no data.
There is an multicast DNS/Bonjour functionality to openHAB. Which announced as

HTTP is announced as _openhab-server._tcp.local. and it's name is openHAB
HTTPS is announced as _openhab-server-ssl._tcp.local. and it's name is openHAB-ssl

Service discovery will return several parameters of openHAB:

IP address (like 192.168.1.20)
TCP port (like 8080)
uri attribute (like /rest)
The base URL for openHAB will look like this: http://192.168.1.20:8080/rest

I try your example code in a little test app with my windows phone 8.1. With the following code

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append("OpenHab data:\n");

        IReadOnlyList<IZeroconfHost> results = await ZeroconfResolver.ResolveAsync("_openhab-server._tcp.local.");

        foreach (var item in results)
        {
            sb.Append(item.DisplayName + "\n");
            sb.Append(item.Id + "\n");
            sb.Append(item.IPAddress + "\n");
            sb.Append(item.Services + "\n");
        }

        txBlock.Text = sb.ToString();
    }

But the results is everytime empty. Any idea whats wrong? My phone is connected to my local lan.

PCL Compatibilty

Installing this nuget package in a Visual Studio 2015, PCL project which targets Windows 10, Xamarin.Android, and Xamarin.iOS fails with the following error. Shouldn't I be able to do this?

Error Could not install package 'Zeroconf 2.3.3'. You are trying to install this package into a project that targets '.NETPortable,Version=v4.5,Profile=Profile7', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author. 0

Thanks

Unable to get txt records

Hello,

Thanks for working on this package. It has been a breeze to get setup. The only problem I'm running into is that the TXT records I'm looking for aren't coming through. Zeroconf will find the host I'm looking for and its IP but the services dictionary is always empty.

Here is the code that I am using.

public async Task StartDiscovery()
 {
    Action<IZeroconfHost> callback = new Action<IZeroconfHost>((IZeroconfHost host) => 
    {
        Debug.WriteLine(host.Services.Count); 
    });

    IReadOnlyList<IZeroconfHost> results = 
        await ZeroconfResolver.ResolveAsync(SERVICE_TYPE, new TimeSpan(0, 0, 10), 4, 2000, callback);
    Debug.WriteLine(results);
}

This is what I see when hitting my breakpoint in the callback.
vs-01

I used an app called All My LAN and it finds the device and all properties.
all_lan

Am I doing anything wrong? I'd really appreciate any help you could provide. Thanks!

Mono.Zeroconf library is not supported for Windows phone8

I want to register a service using Mono.Zeroconf in windows phone 8 but when i try to add this library in wp8 using Nuget then it shows me error that

Install failed. Rolling back...
Install-Package : Could not install package 'Mono.Zeroconf 0.9.0.0'. You are trying to install this package into a project that targets 'WindowsPhone,Version=v8.0', but the
package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.
At line:1 char:1

  • Install-Package Mono.Zeroconf
  • - CategoryInfo          : NotSpecified: (:) [Install-Package], InvalidOperationException
    - FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PowerShell.Commands.InstallPackageCommand
    

Error with Universal Windows apps

when the method BrowseDomainsAsync() is called :

message =>A method was called at an unexpected time. (Exception from HRESULT: 0x8000000E)

stackTrace => at Windows.Networking.Sockets.DatagramSocket.BindServiceNameAsync(String localServiceName, NetworkAdapter adapter)
at Zeroconf.NetworkInterface.d__1.MoveNext()
--- 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 Zeroconf.NetworkInterface.d__0.MoveNext()
--- 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 Zeroconf.ZeroconfResolver.d__7.MoveNext()
--- 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 Zeroconf.ZeroconfResolver.d__5.MoveNext()
--- 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 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at CroutonFramework.Utils.EnumerateAllServicesFromAllHosts.d__0.MoveNext()

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.