/// <summary> /// Event handler for polling timer. Look for new devices and remove old ones. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void FindDeviceTimer_Elapsed(object sender, ElapsedEventArgs e) { TimeSinceReCheck += QueryInterval; if (TimeSinceReCheck - ReCheckInterval > 0) { TimeSinceReCheck = 0; var enumerator = DeviceList.GetEnumerator(); while (enumerator.MoveNext()) { var key = enumerator.Current.Key; try { // If it is time to recheck devices, mark every device as not discovered if (!DeviceList.TryUpdate(key, false, true)) { // TryUpdate returned false. // The device has already was not found the previous recheck cycle. Assume it is gone and notify the user. bool ret; if (DeviceList.TryRemove(key, out ret)) { PrintQueue.Enqueue($"Lost: {key}"); } } } catch (KeyNotFoundException) { } // Device was already removed. } } // Look for new and previously discovered devices MDns.SendQuery(ServiceToQuery); }
/// <summary> /// Called when a DNS reply is received. /// </summary> /// <param name="sender">The MulticastService that sent the query.</param> /// <param name="e">The device that replied.</param> private static void MDns_AnswerReceived(object sender, MessageEventArgs e) { // Extract the DNS-SD service that replied, and the device's IP addresses // Replies might be in Answers or AdditionalRecords so check both var srvRecords = e.Message.AdditionalRecords.Union(e.Message.Answers).OfType <SRVRecord>().Distinct(); var ipv4s = e.Message.AdditionalRecords.Union(e.Message.Answers).OfType <ARecord>().OrderBy(x => x.Address.ToString()); var ipv6s = e.Message.AdditionalRecords.Union(e.Message.Answers).OfType <AAAARecord>().OrderBy(x => x.Address.ToString()); // Ensure the service we found matches the service we are looking for. if (srvRecords.Count() == 0 || !srvRecords.Any(x => x.CanonicalName.EndsWith(ServiceToQuery))) { return; } // Ensure the service supports the desired settings if (DisplayIPv6 && (ipv6s.Count() == 0 || (ipv6s.All(x => !x.Address.IsIPv6LinkLocal) && LinkLocalOnly))) { return; } if (DisplayIPv4 && (ipv4s.Count() == 0 || (ipv4s.All(x => !x.Address.ToString().StartsWith("169.254", StringComparison.InvariantCultureIgnoreCase) && LinkLocalOnly)))) { return; } // Build device information string string output = ""; bool shouldAdd = true; // Only show link-local IPs if requested if (DisplayHostname) { var host = ipv4s.Select(x => x.CanonicalName).FirstOrDefault(); if (host != null) { output += host + " "; } else { shouldAdd = false; } } if (DisplayIPv4) { if (ipv4s.Count() > 0) { foreach (var ip in ipv4s) { output += ip.Address + " "; } } else { shouldAdd = false; } } if (DisplayIPv6) { if (ipv6s.Count() > 0) { foreach (var ip in ipv6s) { if (ip.Address.IsIPv6LinkLocal || !LinkLocalOnly) { output += ip.Address + " "; } } } else { shouldAdd = false; } } if (DisplayPort) { output += srvRecords.First().Port + " "; } if (shouldAdd) { if (DeviceList.TryAdd(output, true)) { PrintQueue.Enqueue($"Discovered: {output}"); } else // Device has been discovered already. { // Mark the device as discovered (again) to ensure it isn't removed by the recheck logic. DeviceList.TryUpdate(output, true, false); } } }