Skip to content

Commit

Permalink
Implement MDNS cache expiration
Browse files Browse the repository at this point in the history
  • Loading branch information
jdomnitz committed Jul 18, 2024
1 parent 7f1c237 commit e4f3a4a
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 19 deletions.
33 changes: 17 additions & 16 deletions TinyDNS/RecordCache.cs → TinyDNS/Cache/RecordCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,19 @@
using System.Collections.Concurrent;
using System.Net;

namespace TinyDNS
namespace TinyDNS.Cache
{
internal sealed class RecordCache
{
private struct RecordEntry : IEquatable<RecordEntry>
{
public Message message;
public IPAddress Address;

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

return false;
}
}

readonly int sizeLimit;
readonly TimeSpan ttl;
private readonly ConcurrentStack<RecordEntry> stack = new ConcurrentStack<RecordEntry>();

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

}

public void Clear()
Expand All @@ -46,15 +35,27 @@ public void Clear()

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

private void Expire()
{
while (stack.TryPeek(out RecordEntry entry))
{
if (entry.Time + ttl > DateTime.Now)
return;
stack.TryPop(out _);
}
}
}
}
31 changes: 31 additions & 0 deletions TinyDNS/Cache/RecordEntry.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// TinyDNS Copyright (C) 2024
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY, without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Affero General Public License for more details.
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

using System.Net;

namespace TinyDNS.Cache
{
internal struct RecordEntry : IEquatable<RecordEntry>
{
public DateTime Time;
public Message message;
public IPAddress Address;

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

return false;
}
}
}
6 changes: 3 additions & 3 deletions TinyDNS/MDNS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using TinyDNS.Cache;
using TinyDNS.Enums;
using TinyDNS.Events;
using TinyDNS.Records;
Expand All @@ -33,7 +34,7 @@ public class MDNS : IDisposable

public delegate Task MessageEventHandler(DNSMsgEvent e);
public event MessageEventHandler? AnswerReceived;
private readonly RecordCache messageCache = new RecordCache(25);
private readonly RecordCache messageCache = new RecordCache(100, TimeSpan.FromSeconds(5));
private readonly bool UNICAST_SUPPORTED;

public MDNS()
Expand All @@ -60,8 +61,7 @@ public async Task Start()
NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface nic in nics)
{
if (nic.OperationalStatus != OperationalStatus.Up ||
!nic.SupportsMulticast ||
if (nic.OperationalStatus != OperationalStatus.Up || !nic.SupportsMulticast ||
nic.NetworkInterfaceType == NetworkInterfaceType.Tunnel ||
nic.NetworkInterfaceType == NetworkInterfaceType.Loopback ||
nic.IsReceiveOnly)
Expand Down

0 comments on commit e4f3a4a

Please sign in to comment.