You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
56 lines
1.7 KiB
C#
56 lines
1.7 KiB
C#
using System.Security.Cryptography;
|
|
using System.Text;
|
|
|
|
namespace OnlineMsgServer.Core
|
|
{
|
|
internal sealed class SeenMessageCache
|
|
{
|
|
private readonly object _lock = new();
|
|
private readonly Dictionary<string, DateTime> _seenUntilUtc = [];
|
|
private readonly int _ttlSeconds;
|
|
|
|
public SeenMessageCache(int ttlSeconds)
|
|
{
|
|
_ttlSeconds = Math.Max(ttlSeconds, 1);
|
|
}
|
|
|
|
public bool TryMark(string senderIdentity, string type, string key, string payload)
|
|
{
|
|
string hash = ComputeHash(senderIdentity, type, key, payload);
|
|
DateTime nowUtc = DateTime.UtcNow;
|
|
|
|
lock (_lock)
|
|
{
|
|
if (_seenUntilUtc.TryGetValue(hash, out DateTime untilUtc) && untilUtc > nowUtc)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
_seenUntilUtc[hash] = nowUtc.AddSeconds(_ttlSeconds);
|
|
|
|
List<string> expiredKeys = [];
|
|
foreach (KeyValuePair<string, DateTime> item in _seenUntilUtc)
|
|
{
|
|
if (item.Value <= nowUtc)
|
|
{
|
|
expiredKeys.Add(item.Key);
|
|
}
|
|
}
|
|
|
|
foreach (string expiredKey in expiredKeys)
|
|
{
|
|
_seenUntilUtc.Remove(expiredKey);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
private static string ComputeHash(string senderIdentity, string type, string key, string payload)
|
|
{
|
|
byte[] bytes = Encoding.UTF8.GetBytes(string.Join("\n", senderIdentity, type, key, payload));
|
|
return Convert.ToHexString(SHA256.HashData(bytes));
|
|
}
|
|
}
|
|
}
|