-
Notifications
You must be signed in to change notification settings - Fork 90
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Xamarin.iOS: Add workaround for new restrictions in iOS 14.5+ regardi…
…ng mDNS browsing
- Loading branch information
ringe
committed
Aug 10, 2021
1 parent
f96ac23
commit 1c9d216
Showing
9 changed files
with
792 additions
and
3 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
#if __IOS__ | ||
using Foundation; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Net; | ||
using System.Net.Sockets; | ||
using System.Runtime.InteropServices; | ||
using UIKit; | ||
|
||
namespace Zeroconf | ||
{ | ||
public enum SockAddrFamily | ||
{ | ||
Inet = 2, | ||
Inet6 = 23 | ||
} | ||
|
||
[StructLayout(LayoutKind.Explicit, Size = 28)] | ||
public struct Sockaddr | ||
{ | ||
[FieldOffset(0)] public byte sin_len; | ||
[FieldOffset(1)] public byte sin_family; | ||
[FieldOffset(2)] public short sin_port; | ||
[FieldOffset(4)] public int sin_addr; | ||
|
||
// IPv6 | ||
[FieldOffset(4)] public uint sin6_flowinfo; | ||
[FieldOffset(8)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] sin6_addr8; | ||
[FieldOffset(24)] public uint sin6_scope_id; | ||
|
||
public static Sockaddr CreateSockaddr(IntPtr bytes) | ||
{ | ||
Sockaddr sock = (Sockaddr)Marshal.PtrToStructure(bytes, typeof(Sockaddr)); | ||
return sock; | ||
} | ||
|
||
public static IPAddress CreateIPAddress(Sockaddr addr) | ||
{ | ||
byte[] bytes = null; | ||
|
||
switch (addr.sin_family) | ||
{ | ||
case (byte)SockAddrFamily.Inet: | ||
byte[] ipv4addr = new byte[4]; | ||
ipv4addr[0] = (byte)(addr.sin_addr & 0x000000FF); | ||
ipv4addr[1] = (byte)((addr.sin_addr & 0x0000FF00) >> 8); | ||
ipv4addr[2] = (byte)((addr.sin_addr & 0x00FF0000) >> 16); | ||
ipv4addr[3] = (byte)((addr.sin_addr & 0xFF000000) >> 24); | ||
bytes = ipv4addr; | ||
break; | ||
case (byte)SockAddrFamily.Inet6: | ||
bytes = addr.sin6_addr8; | ||
break; | ||
default: | ||
#if false | ||
Console.WriteLine($"Unknown socket address family {addr.sin_family}"); | ||
#endif | ||
bytes = null; | ||
break; | ||
} | ||
|
||
return (bytes != null) ? new IPAddress(bytes): null; | ||
} | ||
} | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
#if __IOS__ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Linq; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace Zeroconf | ||
{ | ||
static class ZeroconfNetServiceBrowser | ||
{ | ||
static internal async Task<IReadOnlyList<IZeroconfHost>> ResolveAsync(ResolveOptions options, | ||
Action<IZeroconfHost> callback = null, | ||
CancellationToken cancellationToken = default(CancellationToken), | ||
System.Net.NetworkInformation.NetworkInterface[] netInterfacesToSendRequestOn = null) | ||
{ | ||
if (options == null) throw new ArgumentNullException(nameof(options)); | ||
if (netInterfacesToSendRequestOn != null) | ||
{ | ||
throw new NotImplementedException($"iOS NSNetServiceBrowser/NSNetService does not support per-network interface requests"); | ||
} | ||
|
||
List<IZeroconfHost> combinedResultList = new List<IZeroconfHost>(); | ||
|
||
// Seems you must reuse the one BonjourBrowser (which is really an NSNetServiceBrowser)... multiple instances do not play well together | ||
|
||
BonjourBrowser bonjourBrowser = new BonjourBrowser(); | ||
|
||
foreach (var protocol in options.Protocols) | ||
{ | ||
ResolveOptions perProtocolBrowseOption = new ResolveOptions(protocol) | ||
{ | ||
AllowOverlappedQueries = options.AllowOverlappedQueries, | ||
Retries = options.Retries, | ||
RetryDelay = options.RetryDelay, | ||
ScanQueryType = options.ScanQueryType, | ||
ScanTime = options.ScanTime, | ||
}; | ||
bonjourBrowser.SetResolveOptions(perProtocolBrowseOption, callback, cancellationToken, netInterfacesToSendRequestOn); | ||
|
||
bonjourBrowser.StartServiceSearch(); | ||
|
||
await Task.Delay(options.ScanTime, cancellationToken).ConfigureAwait(false); | ||
|
||
bonjourBrowser.StopServiceSearch(); | ||
|
||
// Simpleminded callback implementation | ||
var results = bonjourBrowser.ReturnZeroconfHostResults(); | ||
foreach (var result in results) | ||
{ | ||
if (callback != null) | ||
{ | ||
callback(result); | ||
} | ||
} | ||
|
||
combinedResultList.AddRange(results); | ||
} | ||
|
||
return combinedResultList; | ||
} | ||
|
||
static internal async Task<ILookup<string, string>> BrowseDomainsAsync(List<string> browseDomainProtocolList, BrowseDomainsOptions options, | ||
Action<string, string> callback = null, | ||
CancellationToken cancellationToken = default(CancellationToken), | ||
System.Net.NetworkInformation.NetworkInterface[] netInterfacesToSendRequestOn = null) | ||
{ | ||
if (options == null) throw new ArgumentNullException(nameof(options)); | ||
if (netInterfacesToSendRequestOn != null) | ||
{ | ||
throw new NotImplementedException($"iOS NSNetServiceBrowser/NSNetService does not support per-network interface requests"); | ||
} | ||
|
||
ResolveOptions resolveOptions = new ResolveOptions(browseDomainProtocolList); | ||
var zeroconfResults = await ResolveAsync(resolveOptions, callback: null, cancellationToken, netInterfacesToSendRequestOn); | ||
|
||
List<IntermediateResult> resultsList = new List<IntermediateResult>(); | ||
foreach (var host in zeroconfResults) | ||
{ | ||
foreach (var service in host.Services) | ||
{ | ||
foreach (var ipAddr in host.IPAddresses) | ||
{ | ||
IntermediateResult b = new IntermediateResult(); | ||
b.ServiceNameAndDomain = service.Key; | ||
b.HostIPAndService = $"{ipAddr}: {BonjourBrowser.GetServiceType(service.Value.Name, includeTcpUdpDelimiter: false)}"; | ||
|
||
resultsList.Add(b); | ||
|
||
// Simpleminded callback implementation | ||
if (callback != null) | ||
{ | ||
callback(service.Key, ipAddr); | ||
} | ||
} | ||
} | ||
} | ||
|
||
ILookup<string, string> results = resultsList.ToLookup(k => k.ServiceNameAndDomain, h => h.HostIPAndService); | ||
return results; | ||
} | ||
|
||
class IntermediateResult | ||
{ | ||
public string ServiceNameAndDomain; | ||
public string HostIPAndService; | ||
} | ||
} | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"msbuild-sdks": { | ||
"MSBuild.Sdk.Extras": "3.0.23" | ||
} | ||
} |