Пример #1
0
        private NetService ProcessPTRRecord(PTRRecord record)
        {
            if (record.Name != _currentServiceType)
            {
                return(null);
            }

            NetService service             = null;
            string     serviceInstanceName = record.DomainName;

            // TTL of zero means we need to remove the service from the list
            if (record.TimeToLive == TimeSpan.Zero)
            {
                RemoveService(serviceInstanceName);
                return(null);
            }

            if (_discoveredServices.ContainsKey(serviceInstanceName))
            {
                service = _discoveredServices[serviceInstanceName];
            }
            else
            {
                service = new NetService(this);
                service.FullServiceInstanceName = serviceInstanceName;

                lock (_discoveredServices)
                    _discoveredServices[serviceInstanceName] = service;
            }

            service.TTLExpires = DateTime.Now + record.TimeToLive;

            return(service);
        }
        /// <summary>
        ///   Advertise a service profile.
        /// </summary>
        /// <param name="service">
        ///   The service profile.
        /// </param>
        /// <remarks>
        ///   Any queries for the service or service instance will be answered with
        ///   information from the profile.
        ///   <para>
        ///   Besides adding the profile's resource records to the <see cref="Catalog"/> PTR records are
        ///   created to support DNS-SD and reverse address mapping (DNS address lookup).
        ///   </para>
        /// </remarks>
        public void Advertise(ServiceProfile service)
        {
            _profiles.Add(service);

            var catalog = NameServer.Catalog;

            catalog.Add(new PTRRecord {
                Name = ServiceName, DomainName = service.QualifiedServiceName
            }, true);
            catalog.Add(new PTRRecord {
                Name = service.QualifiedServiceName, DomainName = service.FullyQualifiedName
            }, true);



            foreach (var subtype in service.Subtypes)
            {
                var ptr = new PTRRecord
                {
                    Name       = DomainName.Join(new DomainName(subtype), SubName, service.QualifiedServiceName),
                    DomainName = service.FullyQualifiedName
                };
                catalog.Add(ptr, true);
            }

            foreach (var r in service.Resources)
            {
                catalog.Add(r, true);
            }

            catalog.IncludeReverseLookupRecords();
        }
Пример #3
0
        private void AnswerReceived(Message message)
        {
            List <PTRRecord> answers = message.Answers.Where(a => a.Name == AtemDeviceInfo.ServiceName).OfType <PTRRecord>().ToList();
            PTRRecord        answer  = answers.FirstOrDefault();

            if (answer == null)
            {
                return;
            }

            if (_debug && answers.Count != 1)
            {
                Console.WriteLine("Too many answers!");
            }

            List <ResourceRecord> records = message.AdditionalRecords;
            SRVRecord             srvRec  = records.OfType <SRVRecord>().FirstOrDefault(r => r.Type == DnsType.SRV && r.Name == answer.DomainName);

            if (srvRec == null)
            {
                if (_debug)
                {
                    Console.WriteLine("Missing SRV record for " + answer.DomainName);
                }
                return;
            }

            AddressRecord aRec = records.OfType <AddressRecord>().FirstOrDefault(r => r.Type == DnsType.A && r.Name == srvRec.Target);

            if (aRec == null)
            {
                if (_debug)
                {
                    Console.WriteLine("Missing A record for " + answer.DomainName);
                }
                return;
            }

            TXTRecord     txtRec  = records.OfType <TXTRecord>().FirstOrDefault(r => r.Type == DnsType.TXT && r.Name == answer.DomainName);
            List <string> strings = txtRec == null ? new List <string>() : txtRec.Strings;

            string name = string.Join(".", answer.DomainName.Labels);

            if (name.EndsWith(AtemDeviceInfo.ServiceName))
            {
                name = name.Substring(0, name.Length - AtemDeviceInfo.ServiceName.Length - 1);
            }

            var dev = new AtemDeviceInfo(name, srvRec.Target.ToString(), DateTime.Now, aRec.Address.ToString(), srvRec.Port, strings);

            lock (_knownDevices) {
                _knownDevices[dev.DeviceId] = dev;
            }

            OnDeviceSeen?.Invoke(this, dev);
        }
 private void ReverseDnsRecord(Output <string> resourceGroupName, Zone privateReverseDns, Output <string> ipAddress, int vnetRangePrefix)
 {
     var nodeRecord = new PTRRecord($"ptr-{DeploymentName}{vnetRangePrefix / 2 + 1}", new PTRRecordArgs
     {
         ResourceGroupName = resourceGroupName,
         ZoneName          = privateReverseDns.Name,
         Name    = ipAddress.Apply(ipAddress => ConstructReveseIpAddress(ipAddress, 3)),
         Records = { $"{DeploymentName}{vnetRangePrefix / 2 + 1}.{ZoneName}" },
         Ttl     = 300
     });
 }
        private PTRRecord DeserializePtrRr(string name, int ttl, byte[] bytes, int start, out int bytesRead)
        {
            var ptr = new PTRRecord()
            {
                Name       = name,
                TimeToLive = ttl,
            };

            ptr.PtrDName = this.dnsSerializer.ParseQuestionName(bytes, start, out bytesRead);

            return(ptr);
        }
Пример #6
0
        /// <summary>
        ///   Add PTR records for each authoritative A/AAAA record.
        /// </summary>
        /// <remarks>
        ///   This enables reverse DNS lookup of all address records.
        /// </remarks>
        public void IncludeReverseLookupRecords()
        {
            var addressRecords = this.Values
                                 .Where(node => node.Authoritative)
                                 .SelectMany(node => node.Resources.OfType <AddressRecord>());

            foreach (var a in addressRecords)
            {
                var ptr = new PTRRecord
                {
                    Class      = a.Class,
                    Name       = new DomainName(a.Address.GetArpaName()),
                    DomainName = a.Name,
                    TTL        = a.TTL
                };
                Add(ptr, authoritative:  true);
            }
        }
Пример #7
0
        public void DuplicateResources()
        {
            var node = new Node();
            var a    = new PTRRecord {
                Name = "a", DomainName = "alpha"
            };
            var b = new PTRRecord {
                Name = "a", DomainName = "alpha"
            };

            Assert.AreEqual(a, b);

            node.Resources.Add(a);
            node.Resources.Add(b);
            node.Resources.Add(a);
            node.Resources.Add(b);
            Assert.AreEqual(1, node.Resources.Count);
        }
        /// <summary>
        ///    Sends an unsolicited MDNS response describing the
        ///    service profile.
        /// </summary>
        /// <param name="profile">
        ///   The profile to describe.
        /// </param>
        /// <remarks>
        ///   Sends a MDNS response <see cref="Message"/> containing the pointer
        ///   and resource records of the <paramref name="profile"/>.
        ///   <para>
        ///   To provide increased robustness against packet loss,
        ///   two unsolicited responses are sent one second apart.
        ///   </para>
        /// </remarks>
        public void Announce(ServiceProfile profile)
        {
            var message = new Message {
                QR = true
            };

            // Add the shared records.
            var ptrRecord = new PTRRecord {
                Name = profile.QualifiedServiceName, DomainName = profile.FullyQualifiedName
            };

            message.Answers.Add(ptrRecord);

            // Add the resource records.
            profile.Resources.ForEach((resource) =>
            {
                message.Answers.Add(resource);
            });

            message.Questions.Add(new Question()
            {
                Name  = profile.ServiceName,
                Class = DnsClass.IN,
                Type  = DnsType.PTR
            });

            foreach (var ip in MulticastService.GetLinkLocalAddresses())
            {
                message.AdditionalRecords.Add(new ARecord()
                {
                    Class   = DnsClass.IN,
                    Type    = DnsType.A,
                    Name    = profile.ServiceName,
                    Address = ip,
                    TTL     = TimeSpan.FromSeconds(120)
                });
            }

            Mdns.Send(message, false);
            Task.Delay(1000).Wait();
            Mdns.Send(message, false);
        }
Пример #9
0
        private Message GetStopPublishMessage()
        {
            Message        message = new Message();
            ResourceRecord record;

            // This message is a response
            message.QueryResponse = true;
            // This is an authoritative response
            message.AuthoritativeAnswer = true;

            // PTR Record
            record = new PTRRecord()
            {
                TimeToLive = TimeSpan.Zero,
                Name       = Type,
                DomainName = FullServiceInstanceName,
            };
            message.AnswerRecords.Add(record);

            return(message);
        }
Пример #10
0
        /// <summary>
        /// Sends a goodbye message for the provided
        /// profile and removes its pointer from the name sever.
        /// </summary>
        /// <param name="profile">The profile to send a goodbye message for.</param>
        public void Unadvertise(ServiceProfile profile)
        {
            var message = new Message {
                QR = true
            };
            var ptrRecord = new PTRRecord {
                Name = profile.QualifiedServiceName, DomainName = profile.FullyQualifiedName
            };

            ptrRecord.TTL = TimeSpan.Zero;

            message.Answers.Add(ptrRecord);
            profile.Resources.ForEach((resource) =>
            {
                resource.TTL = TimeSpan.Zero;
                message.AdditionalRecords.Add(resource);
            });

            Mdns.SendAnswer(message);

            NameServer.Catalog.TryRemove(profile.QualifiedServiceName, out Node _);
        }
Пример #11
0
        /// <summary>
        ///    Sends an unsolicited MDNS response describing the
        ///    service profile.
        /// </summary>
        /// <param name="profile">
        ///   The profile to describe.
        /// </param>
        /// <remarks>
        ///   Sends a MDNS response <see cref="Message"/> containing the pointer
        ///   and resource records of the <paramref name="profile"/>.
        ///   <para>
        ///   To provide increased robustness against packet loss,
        ///   two unsolicited responses are sent one second apart.
        ///   </para>
        /// </remarks>
        public void Announce(ServiceProfile profile)
        {
            var message = new Message {
                QR = true
            };

            // Add the shared records.
            var ptrRecord = new PTRRecord {
                Name = profile.QualifiedServiceName, DomainName = profile.FullyQualifiedName
            };

            message.Answers.Add(ptrRecord);

            // Add the resource records.
            profile.Resources.ForEach((resource) =>
            {
                message.Answers.Add(resource);
            });

            Mdns.SendAnswer(message, checkDuplicate: false);
            Task.Delay(1000).Wait();
            Mdns.SendAnswer(message, checkDuplicate: false);
        }
Пример #12
0
        private Message GetPublishMessage(PublishMessageType type)
        {
            Message        message = new Message();
            ResourceRecord record;

            // This message is a response
            message.QueryResponse = true;
            // This is an authoritative response
            message.AuthoritativeAnswer = true;

            // SRV Record
            record = new SRVRecord()
            {
                TimeToLive = (type == PublishMessageType.Stop) ? TimeSpan.Zero : BroadcastTTL,
                CacheFlush = true,
                Name       = FullServiceInstanceName,
                Target     = Hostname,
                Port       = Port,
            };
            message.AnswerRecords.Add(record);

            // TXT Record
            if (TXTRecordData != null && TXTRecordData.Count > 0)
            {
                record = new TXTRecord()
                {
                    TimeToLive = (type == PublishMessageType.Stop) ? TimeSpan.Zero : BroadcastTTL,
                    CacheFlush = true,
                    Name       = FullServiceInstanceName,
                    Data       = TXTRecordData,
                };
                message.AnswerRecords.Add(record);
            }

            // PTR Record for DNS-SD Service Type Enumeration
            if (type == PublishMessageType.Normal)
            {
                record = new PTRRecord()
                {
                    TimeToLive = BroadcastTTL,
                    Name       = BonjourUtility.DNSSDServiceTypeEnumerationName,
                    DomainName = Type,
                };
                message.AnswerRecords.Add(record);
            }

            // Service PTR Record
            if (type != PublishMessageType.Initial)
            {
                record = new PTRRecord()
                {
                    TimeToLive = (type == PublishMessageType.Stop) ? TimeSpan.Zero : BroadcastTTL,
                    Name       = Type,
                    DomainName = FullServiceInstanceName,
                };
                message.AnswerRecords.Add(record);
            }

            // A Records
            if (type != PublishMessageType.Stop)
            {
                foreach (var ip in IPAddresses)
                {
                    record = new ARecord()
                    {
                        TimeToLive = BroadcastTTL,
                        CacheFlush = true,
                        Name       = Hostname,
                        Address    = ip,
                    };
                    message.AdditionalRecords.Add(record);
                }
            }

            return(message);
        }