/// <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();
        }
        /// <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);
        }
        /// <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 _);
        }