Skip to content

Commit

Permalink
implement probing richardschneider#60
Browse files Browse the repository at this point in the history
  • Loading branch information
jdomnitz committed May 5, 2023
1 parent 7ef60f6 commit bd9992d
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 12 deletions.
2 changes: 1 addition & 1 deletion src/MulticastService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ public void SendAnswer(Message answer, MessageEventArgs query, bool checkDuplica
Send(answer, checkDuplicate, query.RemoteEndPoint);
}

void Send(Message msg, bool checkDuplicate, IPEndPoint remoteEndPoint = null)
internal void Send(Message msg, bool checkDuplicate, IPEndPoint remoteEndPoint = null)
{
var packet = msg.ToByteArray();
if (packet.Length > maxPacketSize)
Expand Down
43 changes: 43 additions & 0 deletions src/ServiceDiscovery.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Xml.Linq;
using Common.Logging;
using Makaretu.Dns.Resolving;

Expand All @@ -17,6 +19,7 @@ public class ServiceDiscovery : IDisposable
static readonly ILog log = LogManager.GetLogger(typeof(ServiceDiscovery));
static readonly DomainName LocalDomain = new DomainName("local");
static readonly DomainName SubName = new DomainName("_sub");
static readonly ushort transaction = (ushort)new Random().Next(10000, int.MaxValue);

/// <summary>
/// The service discovery service name.
Expand All @@ -28,6 +31,7 @@ public class ServiceDiscovery : IDisposable

readonly bool ownsMdns;
List<ServiceProfile> profiles = new List<ServiceProfile>();
bool conflict;

/// <summary>
/// Creates a new instance of the <see cref="ServiceDiscovery"/> class.
Expand Down Expand Up @@ -257,6 +261,40 @@ public void Advertise(ServiceProfile service)
catalog.IncludeReverseLookupRecords();
}

/// <summary>
/// Probe the network to ensure the service is unique.
/// </summary>
/// <param name="profile"></param>
/// <returns>True if thise service conflicts with an existing network service</returns>
public bool Probe(ServiceProfile profile)
{
conflict = false;
Message msg = new Message
{
Opcode = MessageOperation.Query,
QR = false,
Id = transaction
};
msg.Questions.Add(new Question
{
Name = profile.HostName,
Class = DnsClass.IN,
Type = DnsType.ANY
});

Task.Delay(new Random().Next(0, 250)).Wait();
Mdns.Send(msg, false);

Task.Delay(250).Wait();
Mdns.Send(msg, false);

Task.Delay(250).Wait();
Mdns.Send(msg, false);

Task.Delay(250).Wait();
return conflict;
}

/// <summary>
/// Sends an unsolicited MDNS response describing the
/// service profile.
Expand Down Expand Up @@ -335,6 +373,11 @@ void OnAnswer(object sender, MessageEventArgs e)
}

// Any DNS-SD answers?
if (msg.Id == transaction)
{
if (msg.Answers.Count > 0)
conflict = true;
}

var sd = msg.Answers
.OfType<PTRRecord>()
Expand Down
19 changes: 16 additions & 3 deletions test/ServiceDiscoveryTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,11 @@ public void Announce_ContainsSharedRecords()
{
using (var sd = new ServiceDiscovery(mdns))
{
mdns.NetworkInterfaceDiscovered += (s, e) => sd.Announce(service);
mdns.NetworkInterfaceDiscovered += (s, e) =>
{
Assert.IsFalse(sd.Probe(service));
sd.Announce(service);
};
mdns.Start();
Assert.IsTrue(done.WaitOne(TimeSpan.FromSeconds(3)), "announce timeout");
}
Expand Down Expand Up @@ -507,7 +511,12 @@ public void Announce_ContainsResourceRecords()
{
using (var sd = new ServiceDiscovery(mdns))
{
mdns.NetworkInterfaceDiscovered += (s, e) => sd.Announce(service);
mdns.NetworkInterfaceDiscovered +=
(s, e) =>
{
Assert.IsFalse(sd.Probe(service));
sd.Announce(service);
};
mdns.Start();
Assert.IsTrue(done.WaitOne(TimeSpan.FromSeconds(3)), "announce timeout");
}
Expand Down Expand Up @@ -543,7 +552,11 @@ public void Announce_SentTwice()
{
using (var sd = new ServiceDiscovery(mdns))
{
mdns.NetworkInterfaceDiscovered += (s, e) => sd.Announce(service);
mdns.NetworkInterfaceDiscovered += (s, e) =>
{
Assert.IsFalse(sd.Probe(service));
sd.Announce(service);
};
mdns.Start();
Assert.IsTrue(done.WaitOne(TimeSpan.FromSeconds(4)), "announce timeout");
}
Expand Down
10 changes: 2 additions & 8 deletions test/ServiceProfileTest.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
using Makaretu.Dns;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;

namespace Makaretu.Dns
{

[TestClass]
public class ServiveProfileTest
{
Expand Down

0 comments on commit bd9992d

Please sign in to comment.