Skip to content

Commit

Permalink
v0.6
Browse files Browse the repository at this point in the history
Fix record cache eviction
Documentation
  • Loading branch information
jdomnitz committed Jul 19, 2024
1 parent 1179a58 commit f7c2571
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 18 deletions.
26 changes: 14 additions & 12 deletions TinyDNS/Cache/RecordCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,42 +19,44 @@ internal sealed class RecordCache
{
readonly int sizeLimit;
readonly TimeSpan ttl;
private readonly ConcurrentStack<RecordEntry> stack = new ConcurrentStack<RecordEntry>();
private readonly ConcurrentQueue<RecordEntry> cache = new ConcurrentQueue<RecordEntry>();

public RecordCache(int sizeLimit, TimeSpan ttl)
{
this.sizeLimit = sizeLimit;
this.ttl = ttl;

}

public void Clear()
{
stack.Clear();
cache.Clear();
}

public bool Cached(Message message, IPAddress endPoint)
public bool Cached(Message message, IPAddress endPointIP)
{
Expire();
RecordEntry entry = new RecordEntry();
entry.message = message;
entry.Address = endPoint;
entry.Address = endPointIP;
entry.Time = DateTime.Now;
if (stack.Contains(entry))
return true;
stack.Push(entry);
if (stack.Count > sizeLimit)
stack.TryPop(out _);
lock (cache)
{
if (cache.Contains(entry))
return true;
cache.Enqueue(entry);
}
if (cache.Count > sizeLimit)
cache.TryDequeue(out _);
return false;
}

private void Expire()
{
while (stack.TryPeek(out RecordEntry entry))
while (cache.TryPeek(out RecordEntry entry))
{
if (entry.Time + ttl > DateTime.Now)
return;
stack.TryPop(out _);
cache.TryDequeue(out _);
}
}
}
Expand Down
13 changes: 11 additions & 2 deletions TinyDNS/Cache/RecordEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,19 @@ internal struct RecordEntry : IEquatable<RecordEntry>

public bool Equals(RecordEntry other)
{
if (Address.Equals(other.Address))
return message.Equals(other.message);
return message.Equals(other.message);
}

public override bool Equals(object? obj)
{
if (obj is RecordEntry entry)
return Equals(entry);
return false;
}

public override int GetHashCode()
{
return message.GetHashCode();
}
}
}
45 changes: 44 additions & 1 deletion TinyDNS/DNSResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,31 @@ public sealed class DNSResolver
private readonly HashSet<IPAddress> globalNameservers = [];
private ResolverCache cache = new ResolverCache();
private ResolutionMode resolutionMode;
/// <summary>
/// Create a new DNS resolver
/// </summary>
/// <param name="mode">Which strategy to use to resolve queries</param>
public DNSResolver(ResolutionMode mode = ResolutionMode.InsecureOnly)
{
this.resolutionMode = mode;
ReloadNameservers();
NetworkChange.NetworkAddressChanged += (s, e) => ReloadNameservers();
}

/// <summary>
/// Create a new DNS resolver
/// </summary>
/// <param name="nameservers">the nameservers to query</param>
/// <param name="mode">Which strategy to use to resolve queries</param>
public DNSResolver(List<IPAddress> nameservers, ResolutionMode mode = ResolutionMode.InsecureOnly)
{
this.resolutionMode = mode;
foreach (IPAddress nameserver in nameservers)
this.globalNameservers.Add(nameserver);
}

/// <summary>
/// The nameservers to query
/// </summary>
public List<IPAddress> NameServers
{
get
Expand Down Expand Up @@ -68,6 +79,11 @@ private void ReloadNameservers()
}
}

/// <summary>
/// Resolve a hostname to it's IP addresses
/// </summary>
/// <param name="hostname">domain name</param>
/// <returns>domain's IPs</returns>
public async Task<List<IPAddress>> ResolveHost(string hostname)
{
ArgumentNullException.ThrowIfNullOrEmpty(hostname, nameof(hostname));
Expand All @@ -79,6 +95,11 @@ .. await ResolveHostV6(hostname)
return addresses;
}

/// <summary>
/// Resolve a hostname to it's IP v4 addresses
/// </summary>
/// <param name="hostname">domain name</param>
/// <returns>domain's IPs</returns>
public async Task<List<IPAddress>> ResolveHostV4(string hostname)
{
ArgumentNullException.ThrowIfNullOrEmpty(hostname, nameof(hostname));
Expand All @@ -100,6 +121,11 @@ public async Task<List<IPAddress>> ResolveHostV4(string hostname)
return addresses;
}

/// <summary>
/// Resolve a hostname to it's IPv6 addresses
/// </summary>
/// <param name="hostname">domain name</param>
/// <returns>domain's IPs</returns>
public async Task<List<IPAddress>> ResolveHostV6(string hostname)
{
ArgumentNullException.ThrowIfNullOrEmpty(hostname, nameof(hostname));
Expand All @@ -121,6 +147,12 @@ public async Task<List<IPAddress>> ResolveHostV6(string hostname)
return addresses;
}

/// <summary>
/// Lookup the domain name for an IP address
/// </summary>
/// <param name="address"></param>
/// <returns>The response message</returns>
/// <exception cref="ArgumentNullException"></exception>
public async Task<Message?> ResolveIPRecord(IPAddress address)
{
if (address == null)
Expand All @@ -129,6 +161,12 @@ public async Task<List<IPAddress>> ResolveHostV6(string hostname)
bool privateQuery = IsPrivate(address, addressBytes);
return await ResolveQuery(new QuestionRecord(DomainParser.FromIP(addressBytes), DNSRecordType.PTR, false), privateQuery);
}

/// <summary>
/// Lookup the domain name for an IP address
/// </summary>
/// <param name="address"></param>
/// <returns>The domain</returns>
public async Task<string?> ResolveIP(IPAddress address)
{
Message? response = await ResolveIPRecord(address);
Expand All @@ -143,6 +181,11 @@ public async Task<List<IPAddress>> ResolveHostV6(string hostname)
return null;
}

/// <summary>
/// Sends a query and returns the response message
/// </summary>
/// <param name="question"></param>
/// <returns></returns>
public async Task<Message?> ResolveQuery(QuestionRecord question)
{
bool privateQuery = (question.Name.Last() == "local");
Expand Down
6 changes: 6 additions & 0 deletions TinyDNS/DomainParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.

using System.Globalization;
using System.Net;
using System.Text;

namespace TinyDNS
Expand Down Expand Up @@ -108,6 +109,11 @@ public static List<string> Parse(string domain)
return labels;
}

internal static List<string> FromIP(IPAddress address)
{
return FromIP(address.GetAddressBytes());
}

internal static List<string> FromIP(byte[] address)
{
List<string> host;
Expand Down
2 changes: 1 addition & 1 deletion TinyDNS/MDNS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ public async Task Query(List<string> domain, DNSRecordType type, bool unicastRes

public async Task<List<Message>> ResolveInverseQuery(IPAddress address, bool unicastResponse = false)
{
var domain = DomainParser.FromIP(address.GetAddressBytes());
var domain = DomainParser.FromIP(address);
List<Message> responses = new List<Message>();
MessageEventHandler handler = delegate (DNSMessageEvent e)
{
Expand Down
4 changes: 3 additions & 1 deletion TinyDNS/Message.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,9 @@ public bool Equals(Message? other)

public override bool Equals(object? obj)
{
return Equals(obj as Message);
if (obj is Message message)
return Equals(message);
return false;
}

public override string ToString()
Expand Down
2 changes: 1 addition & 1 deletion TinyDNS/TinyDNS.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFrameworks>net80</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>0.5</Version>
<Version>0.6</Version>
<PackageLicenseExpression>AGPL-3.0-or-later</PackageLicenseExpression>
<PackageReadmeFile>README.md</PackageReadmeFile>
<Authors>jdomnitz</Authors>
Expand Down

0 comments on commit f7c2571

Please sign in to comment.