示例#1
0
        public void Reachable_Ipv4()
        {
            var me = MulticastService.GetIPAddresses()
                     .First(a => a.AddressFamily == AddressFamily.InterNetwork && !IPAddress.IsLoopback(a));

            Assert.IsTrue(me.IsReachable(me));
            Assert.IsFalse(me.IsReachable(IPAddress.Parse("1.1.1.1")));

            //var nat = IPAddress.Parse("165.84.19.151"); // NAT PCP assigned address
            //Assert.IsTrue(nat.IsReachable(IPAddress.Parse("1.1.1.1")));
        }
示例#2
0
        public void SubnetMask_All()
        {
            foreach (var a in MulticastService.GetIPAddresses())
            {
                var network = IPNetwork.Parse(a, a.GetSubnetMask());

                Console.WriteLine($"{a} mask {a.GetSubnetMask()} {network}");

                Assert.IsTrue(network.Contains(a), $"{a} is not reachable");
            }
        }
示例#3
0
        public void Disposable()
        {
            using (var mdns = new MulticastService())
            {
                Assert.IsNotNull(mdns);
            }

            using (var mdns = new MulticastService())
            {
                Assert.IsNotNull(mdns);
                mdns.Start();
            }
        }
        public void Disposable()
        {
            using (var sd = new ServiceDiscovery())
            {
                Assert.IsNotNull(sd);
            }

            var mdns = new MulticastService();

            using (var sd = new ServiceDiscovery(mdns))
            {
                Assert.IsNotNull(sd);
            }
        }
示例#5
0
        public async Task ReceiveLegacyUnicastAnswer()
        {
            var service = Guid.NewGuid().ToString() + ".local";
            var ready   = new ManualResetEvent(false);

            var query = new Message();

            query.Questions.Add(new Question
            {
                Name = service,
                Type = DnsType.A
            });
            var packet = query.ToByteArray();
            var client = new UdpClient();

            using (var mdns = new MulticastService())
            {
                mdns.NetworkInterfaceDiscovered += (s, e) => ready.Set();
                mdns.QueryReceived += (s, e) =>
                {
                    var msg = e.Message;
                    if (msg.Questions.Any(q => q.Name == service))
                    {
                        var res = msg.CreateResponse();
                        res.Answers.Add(new ARecord
                        {
                            Name    = service,
                            Address = IPAddress.Parse("127.1.1.1")
                        });
                        mdns.SendAnswer(res, e);
                    }
                };
                mdns.Start();
                Assert.IsTrue(ready.WaitOne(TimeSpan.FromSeconds(1)), "ready timeout");
                await client.SendAsync(packet, packet.Length, "224.0.0.251", 5353);

                var r = await client.ReceiveAsync();

                var response = new Message();
                response.Read(r.Buffer, 0, r.Buffer.Length);
                Assert.IsTrue(response.IsResponse);
                Assert.AreEqual(MessageStatus.NoError, response.Status);
                Assert.IsTrue(response.AA);
                Assert.AreEqual(1, response.Questions.Count);
                var a = (ARecord)response.Answers[0];
                Assert.AreEqual(IPAddress.Parse("127.1.1.1"), a.Address);
                Assert.AreEqual(service, a.Name);
                Assert.AreEqual(TimeSpan.FromSeconds(10), a.TTL);
            }
        }
        public void NicFromPattern()
        {
            var addresses = MulticastService.GetIPAddresses().ToArray();

            foreach (var address in addresses)
            {
                string pattern = address.ToString();
                if (pattern.Contains('.'))
                {
                    pattern = pattern.Substring(0, pattern.LastIndexOf('.')) + ".0/24";
                }
                var nic = MulticastService.GetNetworkInterfaceFromCIDR(pattern);
                Assert.IsNotNull(nic);
            }
        }
示例#7
0
        public void MalformedMessage()
        {
            byte[] malformedMessage = null;
            using (var mdns = new MulticastService())
            {
                mdns.MalformedMessage += (s, e) => malformedMessage = e;

                var msg      = new byte[] { 0xff };
                var endPoint = new IPEndPoint(IPAddress.Loopback, 5353);
                var udp      = new UdpReceiveResult(msg, endPoint);
                mdns.OnDnsMessage(this, udp);

                CollectionAssert.AreEqual(msg, malformedMessage);
            }
        }
示例#8
0
        public void ReceiveAnswer()
        {
            var     service  = Guid.NewGuid().ToString() + ".local";
            var     done     = new ManualResetEvent(false);
            Message response = null;

            var mdns = new MulticastService();

            mdns.NetworkInterfaceDiscovered += (s, e) => mdns.SendQuery(service);
            mdns.QueryReceived += (s, e) =>
            {
                var msg = e.Message;
                if (msg.Questions.Any(q => q.Name == service))
                {
                    var res = msg.CreateResponse();
                    res.Answers.Add(new ARecord
                    {
                        Name    = service,
                        Address = IPAddress.Parse("127.1.1.1")
                    });
                    mdns.SendAnswer(res);
                }
            };
            mdns.AnswerReceived += (s, e) =>
            {
                var msg = e.Message;
                if (msg.Answers.Any(a => a.Name == service))
                {
                    response = msg;
                    done.Set();
                }
            };
            try
            {
                mdns.Start();
                Assert.IsTrue(done.WaitOne(TimeSpan.FromSeconds(1)), "answer timeout");
                Assert.IsNotNull(response);
                Assert.IsTrue(response.IsResponse);
                Assert.AreEqual(MessageStatus.NoError, response.Status);
                Assert.IsTrue(response.AA);
                var a = (ARecord)response.Answers[0];
                Assert.AreEqual(IPAddress.Parse("127.1.1.1"), a.Address);
            }
            finally
            {
                mdns.Stop();
            }
        }
示例#9
0
        public async Task NoDuplicateResponse()
        {
            var service = Guid.NewGuid().ToString() + ".local";

            using (var mdns = new MulticastService())
            {
                var answerCount = 0;
                mdns.NetworkInterfaceDiscovered += (s, e) =>
                {
                    mdns.SendQuery(service);
                    Thread.Sleep(250);
                    mdns.SendQuery(service);
                };
                mdns.QueryReceived += (s, e) =>
                {
                    var msg = e.Message;
                    if (msg.Questions.Any(q => q.Name == service))
                    {
                        var res = msg.CreateResponse();
                        res.Answers.Add(new ARecord
                        {
                            Name    = service,
                            Address = IPAddress.Parse("127.1.1.1")
                        });
                        mdns.SendAnswer(res, checkDuplicate: false);
                    }
                };
                mdns.AnswerReceived += (s, e) =>
                {
                    var msg = e.Message;
                    if (msg.Answers.Any(answer => answer.Name == service))
                    {
                        ++answerCount;
                    }
                    ;
                };
                mdns.Start();
                await Task.Delay(2000);

                Assert.AreEqual(1, answerCount);

                mdns.SendQuery(service);
                await Task.Delay(2000);

                Assert.AreEqual(2, answerCount);
            }
        }
示例#10
0
        public void Discover_ServiceInstance_WithAnswersContainingAdditionRecords()
        {
            var service = new ServiceProfile("y", "_sdtest-2._udp", 1024, new[] { IPAddress.Parse("127.1.1.1") });
            var done    = new ManualResetEvent(false);

            using (var mdns = new MulticastService())
                using (var sd = new ServiceDiscovery(mdns)
                {
                    AnswersContainsAdditionalRecords = true
                })
                {
                    Message discovered = null;

                    mdns.NetworkInterfaceDiscovered += (s, e) =>
                    {
                        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(3)), "instance not found");

                    var additionalRecordsCount =
                        1 + // SRVRecord
                        1 + // TXTRecord
                        1;  // AddressRecord

                    var answersCount = additionalRecordsCount +
                                       1; // PTRRecord

                    Assert.AreEqual(0, discovered.AdditionalRecords.Count);
                    Assert.AreEqual(answersCount, discovered.Answers.Count);
                }
        }
示例#11
0
        public void Multiple_Listeners()
        {
            var ready1 = new ManualResetEvent(false);
            var ready2 = new ManualResetEvent(false);

            using (var mdns1 = new MulticastService())
                using (var mdns2 = new MulticastService())
                {
                    mdns1.NetworkInterfaceDiscovered += (s, e) => ready1.Set();
                    mdns1.Start();

                    mdns2.NetworkInterfaceDiscovered += (s, e) => ready2.Set();
                    mdns2.Start();

                    Assert.IsTrue(ready1.WaitOne(TimeSpan.FromSeconds(1)), "ready1 timeout");
                    Assert.IsTrue(ready2.WaitOne(TimeSpan.FromSeconds(1)), "ready2 timeout");
                }
        }
        public void StartStop_SingleInterface()
        {
            var addresses = MulticastService.GetIPAddresses().ToArray();

            foreach (var address in addresses)
            {
                string pattern = address.ToString();
                if (pattern.Contains('.'))
                {
                    pattern = pattern.Substring(0, pattern.LastIndexOf('.')) + ".0/24";
                }
                var nic  = MulticastService.GetNetworkInterfaceFromCIDR(pattern);
                var mdns = new MulticastService(nic);
                Assert.IsTrue(mdns.IsUsingSingleInterface);
                mdns.Start();
                mdns.Stop();
            }
        }
示例#13
0
        public void ReverseAddressMapping()
        {
            var service     = new ServiceProfile("x9", "_sdtest-1._udp", 1024, new[] { IPAddress.Loopback, IPAddress.IPv6Loopback });
            var arpaAddress = IPAddress.Loopback.GetArpaName();
            var done        = new ManualResetEvent(false);

            var     mdns     = new MulticastService();
            Message response = null;

            mdns.NetworkInterfaceDiscovered += (s, e) =>
                                               mdns.SendQuery(arpaAddress, DnsClass.IN, DnsType.PTR);
            mdns.AnswerReceived += (s, e) =>
            {
                var msg = e.Message;
                if (msg.Answers.OfType <PTRRecord>().Any(p => p.Name == arpaAddress))
                {
                    response = msg;
                    done.Set();
                }
            };
            try
            {
                using (var sd = new ServiceDiscovery(mdns))
                {
                    sd.Advertise(service);
                    mdns.Start();
                    Assert.IsTrue(done.WaitOne(TimeSpan.FromSeconds(1)), "query timeout");
                    var answers = response.Answers
                                  .OfType <PTRRecord>()
                                  .Where(ptr => service.HostName == ptr.DomainName);
                    foreach (var answer in answers)
                    {
                        Assert.AreEqual(arpaAddress, answer.Name);
                        Assert.IsTrue(answer.TTL > TimeSpan.Zero);
                        Assert.AreEqual(DnsClass.IN, answer.Class);
                    }
                }
            }
            finally
            {
                mdns.Stop();
            }
        }
示例#14
0
        public void Resolve_NoAnswer()
        {
            var service = Guid.NewGuid().ToString() + ".local";
            var query   = new Message();

            query.Questions.Add(new Question {
                Name = service, Type = DnsType.ANY
            });
            var cancellation = new CancellationTokenSource(500);

            using (var mdns = new MulticastService())
            {
                mdns.Start();
                ExceptionAssert.Throws <TaskCanceledException>(() =>
                {
                    var _ = mdns.ResolveAsync(query, cancellation.Token).Result;
                });
            }
        }
示例#15
0
        public void Reachable_Loopback_From_Localhost()
        {
            var me = IPAddress.Loopback;

            foreach (var a in MulticastService.GetIPAddresses())
            {
                Assert.IsTrue(me.IsReachable(a), $"{a}");
            }
            Assert.IsFalse(me.IsReachable(IPAddress.Parse("1.1.1.1")));
            Assert.IsFalse(me.IsReachable(IPAddress.Parse("2606:4700:4700::1111")));

            me = IPAddress.IPv6Loopback;
            foreach (var a in MulticastService.GetIPAddresses())
            {
                Assert.IsTrue(me.IsReachable(a), $"{a}");
            }
            Assert.IsFalse(me.IsReachable(IPAddress.Parse("1.1.1.1")));
            Assert.IsFalse(me.IsReachable(IPAddress.Parse("2606:4700:4700::1111")));
        }
示例#16
0
        public void ReceiveErrorAnswer()
        {
            var service = Guid.NewGuid().ToString() + ".local";
            var done    = new ManualResetEvent(false);

            var mdns = new MulticastService();

            mdns.NetworkInterfaceDiscovered += (s, e) => mdns.SendQuery(service);
            mdns.QueryReceived += (s, e) =>
            {
                var msg = e.Message;
                if (msg.Questions.Any(q => q.Name == service))
                {
                    var res = msg.CreateResponse();
                    res.Status = MessageStatus.Refused;
                    res.Answers.Add(new ARecord
                    {
                        Name    = service,
                        Address = IPAddress.Parse("127.1.1.1")
                    });
                    mdns.SendAnswer(res);
                }
            };
            mdns.AnswerReceived += (s, e) =>
            {
                var msg = e.Message;
                if (msg.Answers.Any(a => a.Name == service))
                {
                    done.Set();
                }
            };
            try
            {
                mdns.Start();
                Assert.IsFalse(done.WaitOne(TimeSpan.FromSeconds(0.5)), "answer was not ignored");
            }
            finally
            {
                mdns.Stop();
            }
        }
示例#17
0
        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);
            };

            sd.ServiceInstanceDiscovered += (s, e) =>
            {
                if (e.ServiceInstanceName == service.FullyQualifiedName)
                {
                    Assert.IsNotNull(e.Message);
                    discovered = e.Message;
                    done.Set();
                }
            };
            try
            {
                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();
            }
        }
示例#18
0
        public void Nics()
        {
            var done = new ManualResetEvent(false);
            var mdns = new MulticastService();
            IEnumerable <NetworkInterface> nics = null;

            mdns.NetworkInterfaceDiscovered += (s, e) =>
            {
                nics = e.NetworkInterfaces;
                done.Set();
            };
            mdns.Start();
            try
            {
                Assert.IsTrue(done.WaitOne(TimeSpan.FromSeconds(1)), "timeout");
                Assert.IsTrue(nics.Count() > 0);
            }
            finally
            {
                mdns.Stop();
            }
        }
示例#19
0
        /// <summary>
        ///   Determines if the local IP address can be used by the
        ///   remote address.
        /// </summary>
        /// <param name="local"></param>
        /// <param name="remote"></param>
        /// <returns>
        ///   <b>true</b> if <paramref name="local"/> can be used by <paramref name="remote"/>;
        ///   otherwise, <b>false</b>.
        /// </returns>
        public static bool IsReachable(this IPAddress local, IPAddress remote)
        {
            // Loopback addresses are only reachable when the remote is
            // the same host.
            if (local.Equals(IPAddress.Loopback) || local.Equals(IPAddress.IPv6Loopback))
            {
                return(MulticastService.GetIPAddresses().Contains(remote));
            }

            // IPv4 addresses are reachable when on the same subnet.
            if (local.AddressFamily == AddressFamily.InterNetwork && remote.AddressFamily == AddressFamily.InterNetwork)
            {
                var mask = local.GetSubnetMask();
                if (mask != null)
                {
                    var network = IPNetwork.Parse(local, mask);
                    return(network.Contains(remote));
                }

                // A mask of null should not occur. Is the IP address available on the actual machine or are the local and remote addresses switched in the function call?
                return(false);
            }

            // IPv6 link local addresses are reachable when using the same scope id.
            if (local.AddressFamily == AddressFamily.InterNetworkV6 && remote.AddressFamily == AddressFamily.InterNetworkV6)
            {
                if (local.IsIPv6LinkLocal && remote.IsIPv6LinkLocal)
                {
                    return(local.ScopeId == remote.ScopeId);
                }

                // only interested in link local addresses
                return(false);
            }

            // If nothing of the above matched, they are probably not reachable. -> maybe a IPv4 to IPv6 transmission or vice verse.
            return(false);
        }
示例#20
0
        public void SendNonQuery()
        {
            var query = new Message
            {
                Opcode = MessageOperation.Status,
                QR     = false
            };
            var done = new ManualResetEvent(false);

            var mdns = new MulticastService();

            mdns.NetworkInterfaceDiscovered += (s, e) => mdns.SendQuery(query);
            mdns.QueryReceived += (s, e) => done.Set();
            try
            {
                mdns.Start();
                Assert.IsFalse(done.WaitOne(TimeSpan.FromSeconds(0.5)), "query was not ignored");
            }
            finally
            {
                mdns.Stop();
            }
        }
示例#21
0
        public async Task Resolve()
        {
            var service = Guid.NewGuid().ToString() + ".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.QueryReceived += (s, e) =>
                {
                    var msg = e.Message;
                    if (msg.Questions.Any(q => q.Name == service))
                    {
                        var res = msg.CreateResponse();
                        res.Answers.Add(new ARecord
                        {
                            Name    = service,
                            Address = IPAddress.Parse("127.1.1.1")
                        });
                        mdns.SendAnswer(res);
                    }
                };
                mdns.Start();
                var response = await mdns.ResolveAsync(query, cancellation.Token);

                Assert.IsNotNull(response, "no response");
                Assert.IsTrue(response.IsResponse);
                Assert.AreEqual(MessageStatus.NoError, response.Status);
                Assert.IsTrue(response.AA);
                var a = (ARecord)response.Answers[0];
                Assert.AreEqual(IPAddress.Parse("127.1.1.1"), a.Address);
            }
        }
示例#22
0
        public ServiceProfile(string instanceName, string serviceName, string domainName, ushort port, short ttl, IEnumerable <IPAddress> addresses = null)
        {
            InstanceName = instanceName;
            ServiceName  = serviceName;
            Domain       = domainName;
            var fqn = FullyQualifiedName;

            var simpleServiceName = ServiceName
                                    .Replace("._tcp", "")
                                    .Replace("._udp", "")
                                    .TrimStart('_');

            HostName = $"{InstanceName}.{simpleServiceName}.{Domain}";
            Resources.Add(new SRVRecord
            {
                Name   = fqn,
                Port   = port,
                Target = HostName
            });
            Resources.Add(new TXTRecord
            {
                Name    = fqn,
                Strings = { "txtvers=1" }
            });

            foreach (var address in addresses ?? MulticastService.GetLinkLocalAddresses())
            {
                Resources.Add(AddressRecord.Create(HostName, address));
            }

            servicePtrRecord = new PTRRecord {
                Name = ServiceName, DomainName = QualifiedServiceName, TTL = TimeSpan.FromSeconds(ttl)
            };
            instancePtrRecord = new PTRRecord {
                Name = QualifiedServiceName, DomainName = FullyQualifiedName, TTL = TimeSpan.FromSeconds(ttl)
            };
        }
示例#23
0
        public void Discover_ServiceInstance_with_Subtype()
        {
            var service1 = new ServiceProfile("x", "_sdtest-2._udp", 1024);
            var service2 = new ServiceProfile("y", "_sdtest-2._udp", 1024);

            service2.Subtypes.Add("apiv2");
            var done = new ManualResetEvent(false);
            var mdns = new MulticastService();
            var sd   = new ServiceDiscovery(mdns);

            mdns.NetworkInterfaceDiscovered += (s, e) =>
            {
                sd.QueryServiceInstances("_sdtest-2._udp", "apiv2");
            };

            sd.ServiceInstanceDiscovered += (s, e) =>
            {
                if (e.ServiceInstanceName == service2.FullyQualifiedName)
                {
                    Assert.IsNotNull(e.Message);
                    done.Set();
                }
            };
            try
            {
                sd.Advertise(service1);
                sd.Advertise(service2);
                mdns.Start();
                Assert.IsTrue(done.WaitOne(TimeSpan.FromSeconds(1)), "instance not found");
            }
            finally
            {
                sd.Dispose();
                mdns.Stop();
            }
        }
示例#24
0
 /// <summary>
 ///   Creates a new instance of the <see cref="ServiceDiscovery"/> class with
 ///   the specified <see cref="MulticastService"/>.
 /// </summary>
 /// <param name="mdns">
 ///   The underlaying <see cref="MulticastService"/> to use.
 /// </param>
 public ServiceDiscovery(MulticastService mdns)
 {
     this.Mdns            = mdns;
     mdns.QueryReceived  += OnQuery;
     mdns.AnswerReceived += OnAnswer;
 }
示例#25
0
        public void IPAddresses()
        {
            var addresses = MulticastService.GetIPAddresses().ToArray();

            Assert.AreNotEqual(0, addresses.Length);
        }
示例#26
0
        public void Can_Create()
        {
            var mdns = new MulticastService();

            Assert.IsNotNull(mdns);
        }
示例#27
0
 // Enforce multicast defaults, especially TTL.
 static ServiceProfile()
 {
     // Make sure MulticastService is inited.
     MulticastService.ReferenceEquals(null, null);
 }