Skip to content

Add DNS Lookup functionality to vmPing#113

Open
brunocarne wants to merge 4 commits into
r-smith:mainfrom
brunocarne:master
Open

Add DNS Lookup functionality to vmPing#113
brunocarne wants to merge 4 commits into
r-smith:mainfrom
brunocarne:master

Conversation

@brunocarne
Copy link
Copy Markdown

  • Introduced a new menu item for DNS Lookup in the main window.
  • Added localized string for DNS Lookup in Strings.resx and Strings.Designer.cs.
  • Created DnsLookupService class to handle DNS queries and responses.
  • Implemented DnsLookupWindow for user interaction, including input for hostname/IP and displaying results.
  • Integrated DNS Lookup functionality into the main application flow, allowing users to add DNS probes.
  • Updated project file to include new DnsLookupWindow and DnsLookupService classes.
  • Added icons and UI elements for DNS Lookup in the application.

- Introduced a new menu item for DNS Lookup in the main window.
- Added localized string for DNS Lookup in Strings.resx and Strings.Designer.cs.
- Created DnsLookupService class to handle DNS queries and responses.
- Implemented DnsLookupWindow for user interaction, including input for hostname/IP and displaying results.
- Integrated DNS Lookup functionality into the main application flow, allowing users to add DNS probes.
- Updated project file to include new DnsLookupWindow and DnsLookupService classes.
- Added icons and UI elements for DNS Lookup in the application.
Copilot AI review requested due to automatic review settings April 13, 2026 12:35
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a DNS Lookup feature to vmPing, including a dedicated lookup window and a shared DNS lookup implementation used by both the UI and DNS probes.

Changes:

  • Added a DNS Lookup command/menu item (Ctrl+D) and a new DnsLookupWindow UI.
  • Introduced DnsLookupService to perform forward/reverse lookups (multiple record types, multiple resolvers) and updated DNS probes to use it.
  • Updated resources (strings, icons) and project configuration (new files, target framework bump).

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
vmPing/vmPing.csproj Bumps target framework and includes new DNS lookup UI/service files.
vmPing/Views/MainWindow.xaml Adds DNS Lookup menu entry with icon.
vmPing/Views/MainWindow.xaml.cs Wires command/binding and adds helper to start DNS probes from the lookup window.
vmPing/Views/DnsLookupWindow.xaml New DNS Lookup window layout and controls.
vmPing/Views/DnsLookupWindow.xaml.cs Implements lookup/cancel/copy/add-probe behavior.
vmPing/Classes/DnsLookupService.cs New DNS-over-UDP resolver/formatter used by UI and probe.
vmPing/Classes/Probe-Dns.cs Switches DNS probe execution to use DnsLookupService.
vmPing/ResourceDictionaries/Icons.xaml Adds DNS icon resource.
vmPing/Properties/Strings.resx Adds localized menu string for DNS Lookup.
vmPing/Properties/Strings.Designer.cs Adds generated accessor for Menu_DnsLookup (doc comment issue noted).
README.md Updates documentation to mention the new DNS Lookup entry point and enhanced output.
Files not reviewed (1)
  • vmPing/Properties/Strings.Designer.cs: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +209 to +214
var receiveTask = client.ReceiveAsync();
var timeoutTask = Task.Delay(DefaultTimeoutMilliseconds, token);
var completed = await Task.WhenAny(receiveTask, timeoutTask).ConfigureAwait(false);

if (completed != receiveTask)
throw new TimeoutException();
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cancellation is implemented via Task.Delay(..., token), but if token is canceled while waiting, timeoutTask completes as canceled and this code throws TimeoutException (so UI shows a timeout instead of a cancellation). After WhenAny, check token.IsCancellationRequested/token.ThrowIfCancellationRequested() before throwing TimeoutException, and consider actively closing the UdpClient on cancellation to stop ReceiveAsync promptly.

Copilot uses AI. Check for mistakes.
Comment on lines +198 to +217
var id = GenerateMessageId();
var payload = BuildQuery(queryName, recordType, id);
var endpoint = new IPEndPoint(resolverAddress, 53);

using (var client = new UdpClient(resolverAddress.AddressFamily))
{
client.Client.SendTimeout = DefaultTimeoutMilliseconds;
client.Client.ReceiveTimeout = DefaultTimeoutMilliseconds;

await client.SendAsync(payload, payload.Length, endpoint).ConfigureAwait(false);

var receiveTask = client.ReceiveAsync();
var timeoutTask = Task.Delay(DefaultTimeoutMilliseconds, token);
var completed = await Task.WhenAny(receiveTask, timeoutTask).ConfigureAwait(false);

if (completed != receiveTask)
throw new TimeoutException();

var result = await receiveTask.ConfigureAwait(false);
return ParseResponse(result.Buffer);
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The generated DNS message ID (id) is never validated against the received response. Because UdpClient.ReceiveAsync() can return any datagram sent to the socket, this can misassociate responses (and also leaves ushort id = ... in ParseResponse unused). Parse the response ID and verify it matches the request ID before accepting the packet (otherwise keep waiting / treat as invalid).

Copilot uses AI. Check for mistakes.
Comment on lines +52 to +57
var reports = new List<DnsLookupReport>();
foreach (var resolver in resolvers)
{
token.ThrowIfCancellationRequested();
reports.Add(await QueryResolverAsync(trimmedInput, queryName, resolver, recordTypes, token).ConfigureAwait(false));
}
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DNS queries are executed sequentially across resolvers (and then sequentially per record type inside QueryResolverAsync). With 3+ resolvers and a 4s timeout, worst-case lookups can take a long time and make the UI feel hung. Consider running resolver queries in parallel (e.g., Task.WhenAll with a small concurrency limit) and aggregating results when all complete or cancellation occurs.

Copilot uses AI. Check for mistakes.
Comment thread vmPing/Classes/DnsLookupService.cs Outdated
Comment on lines +49 to +50
if (resolvers.Count == 0)
resolvers.AddRange(PublicResolvers);
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetResolvers() always yields PublicResolvers (after local resolvers), so resolvers.Count will never be 0 here and this fallback block is effectively dead code. Either remove the if (resolvers.Count == 0) branch, or change GetResolvers() to only return local resolvers and keep the fallback logic here.

Suggested change
if (resolvers.Count == 0)
resolvers.AddRange(PublicResolvers);

Copilot uses AI. Check for mistakes.
Comment on lines +115 to +116
private static async Task<DnsLookupReport> QueryResolverAsync(string originalInput, string queryName, DnsResolver resolver, IReadOnlyList<DnsRecordType> recordTypes, CancellationToken token)
{
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

originalInput is passed into QueryResolverAsync but never used. This makes the API misleading and suggests missing functionality (e.g., reporting the original input). Remove the parameter or use it in the report output.

Copilot uses AI. Check for mistakes.
Comment on lines +857 to +860

private enum DnsRecordType : ushort
{
A = 1,
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There appears to be an embedded control character at the end of the private enum DnsRecordType : ushort line (shows up as ushort followed by a stray character). This can cause noisy diffs and can break some tooling/linters—please remove the non-printable character and ensure the file uses consistent line endings/encoding.

Copilot uses AI. Check for mistakes.
Comment on lines +233 to +237
existingProbe.Hostname = probeHostname;

var aliasKey = normalizedHost.ToLowerInvariant();
existingProbe.Alias = null;
if (_Aliases.TryGetValue(aliasKey, out var aliasValue))
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aliasKey is derived from normalizedHost, which may still include the D/ prefix if the caller passes it. Since Probe.StartStop() strips the D/ prefix (and aliases are typically keyed by the raw host), this path will fail to apply an alias when host starts with D/. Consider deriving aliasKey from the unprefixed hostname (e.g., strip D/ before the lookup).

Copilot uses AI. Check for mistakes.
Comment on lines +42 to +44
cancellation?.Cancel();
cancellation = new CancellationTokenSource();
isLookupInProgress = true;
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When starting a new lookup, the previous CancellationTokenSource is canceled but not disposed before being replaced. Over multiple lookups this can leak wait handles. Dispose the old CTS (e.g., capture to a local, cancel+dispose) before assigning a new one.

Copilot uses AI. Check for mistakes.
Comment on lines 504 to +508
/// <summary>
/// Looks up a localized string similar to Traceroute.
/// </summary>
/// <summary>
/// Looks up a localized string similar to DNS Lookup.
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The XML doc comments here are malformed: there are two consecutive <summary> blocks ("Traceroute" then "DNS Lookup"), which leaves Menu_Traceroute without its own summary and can confuse doc generation tooling. Regenerate Strings.Designer.cs from the .resx or fix the comment blocks so each property has exactly one <summary>.

Copilot uses AI. Check for mistakes.
@r-smith
Copy link
Copy Markdown
Owner

r-smith commented Apr 30, 2026

vmPing does already have a DNS lookup feature, unfortunately the docs are lacking. For the hostname, do D/google.com for example. Putting D/ (uppercase D) in front of the target host does a DNS lookup. This is a feature I was planning to change around a bit to make it simpler and more discoverable.

I'll look over your commits next week to see what's added. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants