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"); } }
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()); }
/// <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(); }
/// <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); }
private IPAddress[] resolve() { if (llmnr == null) { llmnr = new Llmnr(); } if (mdns == null) { mdns = new Mdns(); } return(NameResolving.ResolveAsync(this.service, 2000, llmnr, mdns).Result); }
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; }
/// <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); }
/// <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 _); }
/// <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); }
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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }