Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added using of NetworkChange.NetworkAddressChanged instead of Timer #36

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions Spike/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@ static void Main(string[] args)
};
LogManager.Adapter = new ConsoleOutLoggerFactoryAdapter(properties);

var mdns = new MulticastService
{
NetworkInterfaceDiscoveryInterval = TimeSpan.FromSeconds(1),
};
var mdns = new MulticastService();

foreach (var a in MulticastService.GetIPAddresses())
{
Expand Down
77 changes: 25 additions & 52 deletions src/MulticastService.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
using Common.Logging;
using System;
using System.Collections.Generic;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Common.Logging;

namespace Makaretu.Dns
{
Expand Down Expand Up @@ -82,7 +82,8 @@ static MulticastService()
/// Always use socketLock to gain access.
/// </remarks>
UdpClient sender;
readonly Object senderLock = new object();

readonly object senderLock = new object();

/// <summary>
/// Raised when any local MDNS service sends a query.
Expand Down Expand Up @@ -123,23 +124,10 @@ public MulticastService()
throw new InvalidOperationException("No OS support for IPv4 nor IPv6");

mdnsEndpoint = new IPEndPoint(
ip6 ? MulticastAddressIp6 : MulticastAddressIp4,
ip6 ? MulticastAddressIp6 : MulticastAddressIp4,
MulticastPort);
}

/// <summary>
/// The interval for discovering network interfaces.
/// </summary>
/// <value>
/// Default is 2 minutes.
/// </value>
/// <remarks>
/// When the interval is reached a task is started to discover any
/// new network interfaces.
/// </remarks>
/// <seealso cref="NetworkInterfaceDiscovered"/>
public TimeSpan NetworkInterfaceDiscoveryInterval { get; set; } = TimeSpan.FromMinutes(2);

/// <summary>
/// Get the network interfaces that are useable.
/// </summary>
Expand Down Expand Up @@ -200,7 +188,7 @@ public void Start()
knownNics.Clear();

// Start a task to find the network interfaces.
PollNetworkInterfaces();
FindNetworkInterfaces();
}

/// <summary>
Expand Down Expand Up @@ -235,26 +223,9 @@ public void Stop()
}
}

async void PollNetworkInterfaces()
void OnNetworkAddressChanged(object sender, EventArgs e)
{
var cancel = serviceCancellation.Token;
try
{
while (!cancel.IsCancellationRequested)
{
FindNetworkInterfaces();
await Task.Delay(NetworkInterfaceDiscoveryInterval, cancel);
}
}
catch (TaskCanceledException)
{
// eat it
}
catch (Exception e)
{
log.Error(e);
// eat it.
}
FindNetworkInterfaces();
}

void FindNetworkInterfaces()
Expand Down Expand Up @@ -282,6 +253,7 @@ void FindNetworkInterfaces()
}
}
}

knownNics = currentNics;

// If any NIC change, then get new sockets.
Expand All @@ -297,17 +269,20 @@ void FindNetworkInterfaces()
sender.MulticastLoopback = true;

// Start a task to listen for MDNS messages.
Listener();
Task.Factory.StartNew(async () => await ListenerAsync());
}

// Tell others.
if (newNics.Any())
{
{
NetworkInterfaceDiscovered?.Invoke(this, new NetworkInterfaceEventArgs
{
NetworkInterfaces = newNics
});
}

NetworkChange.NetworkAddressChanged -= OnNetworkAddressChanged;
NetworkChange.NetworkAddressChanged += OnNetworkAddressChanged;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why removing then adding again?

}

/// <inheritdoc />
Expand Down Expand Up @@ -547,7 +522,7 @@ void OnDnsMessage(byte[] datagram, int length)
/// A background task to receive DNS messages from this and other MDNS services. It is
/// cancelled via <see cref="Stop"/>. All messages are forwarded to <see cref="OnDnsMessage"/>.
/// </remarks>
async void Listener()
async Task ListenerAsync()
{
var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);

Expand All @@ -558,25 +533,25 @@ async void Listener()
}

listenerCancellation = new CancellationTokenSource();

UdpClient receiver = new UdpClient(mdnsEndpoint.AddressFamily);
if (isWindows)
{
receiver.ExclusiveAddressUse = false;
}
receiver.Client.SetSocketOption(
SocketOptionLevel.Socket,
SocketOptionName.ReuseAddress,
true);
receiver.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
if (isWindows)
{
receiver.ExclusiveAddressUse = false;
}
var endpoint = new IPEndPoint(ip6 ? IPAddress.IPv6Any : IPAddress.Any, MulticastPort);
receiver.Client.Bind(endpoint);
receiver.JoinMulticastGroup(mdnsEndpoint.Address);
receiver.JoinMulticastGroup(mdnsEndpoint.Address, endpoint.Address);

var cancel = listenerCancellation.Token;

cancel.Register(() => receiver.Dispose());

try
{
while (!cancel.IsCancellationRequested)
Expand All @@ -592,11 +567,10 @@ async void Listener()
// eat the exception
}

receiver.Dispose();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the receiver be disposed?

if (listenerCancellation != null)
using (var lc = listenerCancellation)
{
listenerCancellation.Dispose();
listenerCancellation = null;
lc?.Cancel();
}
}

Expand All @@ -618,6 +592,5 @@ public void Dispose()
}

#endregion

}
}
55 changes: 32 additions & 23 deletions src/ServiceDiscovery.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
using Common.Logging;
using Makaretu.Dns.Resolving;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using Common.Logging;
using Makaretu.Dns.Resolving;

namespace Makaretu.Dns
{
Expand Down Expand Up @@ -80,7 +79,8 @@ public ServiceDiscovery(MulticastService mdns)
/// <value>
/// Is used to answer questions.
/// </value>
public NameServer NameServer { get; } = new NameServer {
public NameServer NameServer { get; } = new NameServer
{
Catalog = new Catalog(),
AnswerAllQuestions = true
};
Expand Down Expand Up @@ -196,31 +196,39 @@ void OnQuery(object sender, MessageEventArgs e)
var request = e.Message;

if (log.IsDebugEnabled)
{
log.Debug($"got query for {request.Questions[0].Name} {request.Questions[0].Type}");
}

var response = NameServer.ResolveAsync(request).Result;
if (response.Status == MessageStatus.NoError)

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

if (AnswersContainsAdditionalRecords)
{
response.Answers.AddRange(response.AdditionalRecords);
response.AdditionalRecords.Clear();
}
if (AnswersContainsAdditionalRecords)
{
response.Answers.AddRange(response.AdditionalRecords);
}

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

Mdns.SendAnswer(response);

Mdns.SendAnswer(response);
if (log.IsDebugEnabled)
log.Debug($"sent answer {response.Answers[0]}");
//Console.WriteLine($"Response time {(DateTime.Now - request.CreationTime).TotalMilliseconds}ms");
if (log.IsDebugEnabled)
{
log.Debug($"sent answer {response.Answers[0]}");
}
//Console.WriteLine($"Response time {(DateTime.Now - request.CreationTime).TotalMilliseconds}ms");
}

#region IDisposable Support
#region IDisposable Support

/// <inheritdoc />
protected virtual void Dispose(bool disposing)
Expand All @@ -245,7 +253,8 @@ public void Dispose()
{
Dispose(true);
}
#endregion

#endregion
}

}
50 changes: 23 additions & 27 deletions test/ServiceDiscoveryTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,39 +194,35 @@ public void Discover_ServiceInstance_WithAnswersContainingAdditionRecords()
{
var service = new ServiceProfile("y", "_sdtest-2._udp", 1024);
var done = new ManualResetEvent(false);
var mdns = new MulticastService();
var sd = new ServiceDiscovery(mdns)
{
AnswersContainsAdditionalRecords = true
};
Message discovered = null;
mdns.NetworkInterfaceDiscovered += (s, e) =>
{
sd.QueryServiceInstances(service.ServiceName);
};
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should not be changing the existing tests. This implies a breaking change.


sd.ServiceInstanceDiscovered += (s, e) =>
using (var mdns = new MulticastService())
using (var sd = new ServiceDiscovery(mdns) { AnswersContainsAdditionalRecords = true })
{
if (e.ServiceInstanceName == service.FullyQualifiedName)
Message discovered = null;

mdns.NetworkInterfaceDiscovered += (s, e) =>
{
Assert.IsNotNull(e.Message);
discovered = e.Message;
done.Set();
}
};
try
{
sd.QueryServiceInstances(service.ServiceName);
};

sd.ServiceInstanceDiscovered += (s, e) =>
{
if (e.ServiceInstanceName == service.FullyQualifiedName)
{
Assert.IsNotNull(e.Message);
discovered = e.Message;
done.Set();
}
};

sd.Advertise(service);

mdns.Start();

Assert.IsTrue(done.WaitOne(TimeSpan.FromSeconds(1)), "instance not found");
Assert.AreEqual(0, discovered.AdditionalRecords.Count);
Assert.IsTrue(discovered.Answers.Count > 1);
}
finally
{
sd.Dispose();
mdns.Stop();
}
Assert.IsTrue(discovered.AdditionalRecords.Count > 0);
Assert.IsTrue(discovered.Answers.Count > 0);
}
}

}
Expand Down