Beispiel #1
0
        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)
            {
                // 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);
                if (log.IsDebugEnabled)
                {
                    log.Debug($"sent answer {response.Answers[0]}");
                }
                //Console.WriteLine($"Response time {(DateTime.Now - request.CreationTime).TotalMilliseconds}ms");
            }
        }
Beispiel #2
0
        void OnQuery(object sender, MessageEventArgs e)
        {
            var request = e.Message;

            System.Diagnostics.Trace.TraceInformation($"Query from {e.RemoteEndPoint}");
            System.Diagnostics.Trace.WriteLine(request);

            // Determine if this query is requesting a unicast response
            // and normalise the Class.
            var QU = false; // unicast query response?

            foreach (var r in request.Questions)
            {
                if (((ushort)r.Class & 0x8000) != 0)
                {
                    QU      = true;
                    r.Class = (DnsClass)((ushort)r.Class & 0x7fff);
                }
            }

            var response = NameServer.ResolveAsync(request).Result;

            if (response.Status != MessageStatus.NoError)
            {
                return;
            }

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

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

            if (!response.Answers.Any(a => a.Name == ServiceName))
            {
                ;
            }

            if (QU)
            {
                // TODO: Send a Unicast response if required.
                Mdns.SendAnswer(response, e);
            }
            else
            {
                Mdns.SendAnswer(response, e);
            }

            System.Diagnostics.Trace.TraceInformation($"Sending answer");
            System.Diagnostics.Trace.WriteLine(response);
            //Console.WriteLine($"Response time {(DateTime.Now - request.CreationTime).TotalMilliseconds}ms");
        }
        void OnQuery(object sender, MessageEventArgs e)
        {
            var request = e.Message;

            _logger.LogDebug($"Query from {e.RemoteEndPoint}");

            _logger.LogTrace(request.ToString());

            // Determine if this query is requesting a unicast response
            // and normalise the Class.
            var qu = false; // unicast query response?

            foreach (var r in request.Questions)
            {
                if (((ushort)r.Class & 0x8000) != 0)
                {
                    qu      = true;
                    r.Class = (DnsClass)((ushort)r.Class & 0x7fff);
                }
            }

            var response = NameServer.ResolveAsync(request).Result;

            if (response.Status != MessageStatus.NoError)
            {
                return;
            }

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

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

            if (response.Answers.All(a => a.Name != ServiceName))
            {
                ;
            }

            if (qu)
            {
                // TODO: Send a Unicast response if required.
                Mdns.SendAnswer(response, e);
            }
            else
            {
                Mdns.SendAnswer(response, e);
            }

            _logger.LogDebug($"Sending answer");
            _logger.LogTrace(response.ToString());
        }
Beispiel #4
0
        /// <summary>
        ///   Creates a new instance of the <see cref="ServiceDiscovery"/> class.
        /// </summary>
        public ServiceDiscovery()
            : this(new MulticastService())
        {
            ownsMdns = true;

            // Auto start.
            Mdns.Start();
        }
        /// <summary>
        ///   Creates a new instance of the <see cref="ServiceDiscovery"/> class.
        /// </summary>
        public ServiceDiscovery(ILogger logger)
            : this(logger, new MulticastService())
        {
            _ownsMdns = true;

            // Auto start.
            Mdns.Start();
        }
Beispiel #6
0
        /// <summary>
        ///   Asks instances of the specified service with the subtype to send details.
        /// </summary>
        /// <param name="service">
        ///   The service name to query. Typically of the form "_<i>service</i>._tcp".
        /// </param>
        /// <param name="subtype">
        ///   The feature that is needed.
        /// </param>
        /// <remarks>
        ///   When an answer is received the <see cref="ServiceInstanceDiscovered"/> event is raised.
        /// </remarks>
        /// <seealso cref="ServiceProfile.ServiceName"/>
        public void QueryServiceInstances(DomainName service, string subtype)
        {
            var name = DomainName.Join(
                new DomainName(subtype),
                SubName,
                service,
                LocalDomain);

            Mdns.SendQuery(name, type: DnsType.PTR);
        }
Beispiel #7
0
 private IPAddress[] resolve()
 {
     if (llmnr == null)
     {
         llmnr = new Llmnr();
     }
     if (mdns == null)
     {
         mdns = new Mdns();
     }
     return(NameResolving.ResolveAsync(this.service, 2000, llmnr, mdns).Result);
 }
Beispiel #8
0
 public SshClientWrapper(string service, string IPAddress, ushort port, string username, string password)
 {
     sshClient        = null;
     llmnr            = null;
     mdns             = null;
     connectThread    = null;
     enabled          = false;
     hasConnected     = false;
     lastDisconnected = DateTime.Now.Subtract(TimeSpan.FromMilliseconds(3000));
     this.service     = service;
     this.IPAddress   = IPAddress;
     this.port        = port;
     this.username    = username;
     this.password    = password;
 }
Beispiel #9
0
 /// <inheritdoc />
 protected virtual void Dispose(bool disposing)
 {
     if (disposing)
     {
         if (Mdns != null)
         {
             Mdns.QueryReceived  -= OnQuery;
             Mdns.AnswerReceived -= OnAnswer;
             if (ownsMdns)
             {
                 Mdns.Dispose();
             }
             Mdns = null;
         }
     }
 }
        /// <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);
        }
Beispiel #11
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 _);
        }
Beispiel #12
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);
        }
Beispiel #13
0
        void OnQuery(object sender, MessageEventArgs e)
        {
            // Should run asynchronously because otherwise incoming messages may overlap and it may not be responded to every message.
            Task.Run(() =>
            {
                var request = e.Message;

                if (log.IsDebugEnabled)
                {
                    log.Debug($"Query from {e.RemoteEndPoint}");
                }

                if (log.IsTraceEnabled)
                {
                    log.Trace(request);
                }

                // Determine if this query is requesting a unicast response
                // and normalise the Class.

                var QU = false;                         // unicast query response?
                foreach (var r in request.Questions)
                {
                    if (((ushort)r.Class & 0x8000) != 0)
                    {
                        QU      = true;
                        r.Class = (DnsClass)((ushort)r.Class & 0x7fff);
                    }
                }

                var response = NameServer.ResolveAsync(request).Result;

                if (response.Status != MessageStatus.NoError)
                {
                    return;
                }

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

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

                if (!response.Answers.Any(a => a.Name == ServiceName))
                {
                    ;
                }

                // Only return address records that the querier can reach.
                response.RemoveUnreachableRecords(e.RemoteEndPoint.Address);

                if (QU)
                {
                    // TODO: Send a Unicast response if required.
                    Mdns.SendAnswer(response, e);
                }
                else
                {
                    Mdns.SendAnswer(response, e);
                }

                if (log.IsDebugEnabled)
                {
                    log.Debug($"Sending answer");
                }

                if (log.IsTraceEnabled)
                {
                    log.Trace(response);
                }
            }).ConfigureAwait(false);
        }
Beispiel #14
0
 /// <summary>
 ///   Asks instances of the specified service to send details.
 /// </summary>
 /// <param name="service">
 ///   The service name to query. Typically of the form "_<i>service</i>._tcp".
 /// </param>
 /// <remarks>
 ///   When an answer is received the <see cref="ServiceInstanceDiscovered"/> event is raised.
 /// </remarks>
 /// <seealso cref="ServiceProfile.ServiceName"/>
 public void QueryServiceInstances(string service)
 {
     Mdns.SendQuery(service + ".local", type: DnsType.PTR);
 }
Beispiel #15
0
 /// <summary>
 ///   Asks instances of the specified service to send details.
 ///   accepts unicast and/or broadcast answers.
 /// </summary>
 /// <param name="service">
 ///   The service name to query. Typically of the form "_<i>service</i>._tcp".
 /// </param>
 /// <remarks>
 ///   When an answer is received the <see cref="ServiceInstanceDiscovered"/> event is raised.
 /// </remarks>
 /// <seealso cref="ServiceProfile.ServiceName"/>
 public void QueryUnicastServiceInstances(DomainName service)
 {
     Mdns.SendUnicastQuery(DomainName.Join(service, LocalDomain), type: DnsType.PTR);
 }
Beispiel #16
0
 /// <summary>
 ///    Asks other MDNS services to send their service names;
 ///    accepts unicast and/or broadcast answers.
 /// </summary>
 /// <remarks>
 ///   When an answer is received the <see cref="ServiceDiscovered"/> event is raised.
 /// </remarks>
 public void QueryUnicastAllServices()
 {
     Mdns.SendUnicastQuery(ServiceName, type: DnsType.PTR);
 }
Beispiel #17
0
 /// <summary>
 ///    Asks other MDNS services to send their service names.
 /// </summary>
 /// <remarks>
 ///   When an answer is received the <see cref="ServiceDiscovered"/> event is raised.
 /// </remarks>
 public void QueryAllServices()
 {
     Mdns.SendQuery(ServiceName, type: DnsType.PTR);
 }