Skip to content

Commit e4f3a4a

Browse files
committed
Implement MDNS cache expiration
1 parent 7f1c237 commit e4f3a4a

File tree

3 files changed

+51
-19
lines changed

3 files changed

+51
-19
lines changed
Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,30 +13,19 @@
1313
using System.Collections.Concurrent;
1414
using System.Net;
1515

16-
namespace TinyDNS
16+
namespace TinyDNS.Cache
1717
{
1818
internal sealed class RecordCache
1919
{
20-
private struct RecordEntry : IEquatable<RecordEntry>
21-
{
22-
public Message message;
23-
public IPAddress Address;
24-
25-
public bool Equals(RecordEntry other)
26-
{
27-
if (Address.Equals(other.Address))
28-
return message.Equals(other.message);
29-
30-
return false;
31-
}
32-
}
33-
3420
readonly int sizeLimit;
21+
readonly TimeSpan ttl;
3522
private readonly ConcurrentStack<RecordEntry> stack = new ConcurrentStack<RecordEntry>();
3623

37-
public RecordCache(int sizeLimit)
24+
public RecordCache(int sizeLimit, TimeSpan ttl)
3825
{
3926
this.sizeLimit = sizeLimit;
27+
this.ttl = ttl;
28+
4029
}
4130

4231
public void Clear()
@@ -46,15 +35,27 @@ public void Clear()
4635

4736
public bool Cached(Message message, IPAddress endPoint)
4837
{
38+
Expire();
4939
RecordEntry entry = new RecordEntry();
5040
entry.message = message;
5141
entry.Address = endPoint;
42+
entry.Time = DateTime.Now;
5243
if (stack.Contains(entry))
5344
return true;
5445
stack.Push(entry);
5546
if (stack.Count > sizeLimit)
5647
stack.TryPop(out _);
5748
return false;
5849
}
50+
51+
private void Expire()
52+
{
53+
while (stack.TryPeek(out RecordEntry entry))
54+
{
55+
if (entry.Time + ttl > DateTime.Now)
56+
return;
57+
stack.TryPop(out _);
58+
}
59+
}
5960
}
6061
}

TinyDNS/Cache/RecordEntry.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// TinyDNS Copyright (C) 2024
2+
//
3+
// This program is free software: you can redistribute it and/or modify
4+
// it under the terms of the GNU Affero General Public License as published by
5+
// the Free Software Foundation, either version 3 of the License, or any later version.
6+
// This program is distributed in the hope that it will be useful,
7+
// but WITHOUT ANY WARRANTY, without even the implied warranty of
8+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9+
// See the GNU Affero General Public License for more details.
10+
// You should have received a copy of the GNU Affero General Public License
11+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
12+
13+
using System.Net;
14+
15+
namespace TinyDNS.Cache
16+
{
17+
internal struct RecordEntry : IEquatable<RecordEntry>
18+
{
19+
public DateTime Time;
20+
public Message message;
21+
public IPAddress Address;
22+
23+
public bool Equals(RecordEntry other)
24+
{
25+
if (Address.Equals(other.Address))
26+
return message.Equals(other.message);
27+
28+
return false;
29+
}
30+
}
31+
}

TinyDNS/MDNS.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
using System.Net.NetworkInformation;
1515
using System.Net.Sockets;
1616
using System.Runtime.InteropServices;
17+
using TinyDNS.Cache;
1718
using TinyDNS.Enums;
1819
using TinyDNS.Events;
1920
using TinyDNS.Records;
@@ -33,7 +34,7 @@ public class MDNS : IDisposable
3334

3435
public delegate Task MessageEventHandler(DNSMsgEvent e);
3536
public event MessageEventHandler? AnswerReceived;
36-
private readonly RecordCache messageCache = new RecordCache(25);
37+
private readonly RecordCache messageCache = new RecordCache(100, TimeSpan.FromSeconds(5));
3738
private readonly bool UNICAST_SUPPORTED;
3839

3940
public MDNS()
@@ -60,8 +61,7 @@ public async Task Start()
6061
NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
6162
foreach (NetworkInterface nic in nics)
6263
{
63-
if (nic.OperationalStatus != OperationalStatus.Up ||
64-
!nic.SupportsMulticast ||
64+
if (nic.OperationalStatus != OperationalStatus.Up || !nic.SupportsMulticast ||
6565
nic.NetworkInterfaceType == NetworkInterfaceType.Tunnel ||
6666
nic.NetworkInterfaceType == NetworkInterfaceType.Loopback ||
6767
nic.IsReceiveOnly)

0 commit comments

Comments
 (0)