feat: implement authenticated NAT mediator (#11)
quality-gate / quality (push) Successful in 59s

Closes #11
This commit is contained in:
KyuubiYoru
2026-07-16 07:37:02 +02:00
parent 1baa1055dc
commit 6d076c281a
19 changed files with 1660 additions and 174 deletions
@@ -4,6 +4,7 @@ namespace FinalFactory.Rendezvous.Server.State;
internal sealed class InMemoryEphemeralRendezvousStore : IEphemeralRendezvousStore
{
private static readonly TimeSpan UdpMaintenanceInterval = TimeSpan.FromSeconds(1);
private readonly object _gate = new();
private readonly EphemeralStoreOptions _options;
private readonly IMonotonicClock _monotonicClock;
@@ -19,6 +20,8 @@ internal sealed class InMemoryEphemeralRendezvousStore : IEphemeralRendezvousSto
private readonly Dictionary<string, TimeSpan> _replay = new(StringComparer.Ordinal);
private readonly Dictionary<string, TimeSpan> _revocations = new(StringComparer.Ordinal);
private TimeSpan? _drainDeadline;
private TimeSpan _nextUdpMaintenance;
private long _maintenanceSweepCount;
private bool _available = true;
public InMemoryEphemeralRendezvousStore(
@@ -38,6 +41,7 @@ internal sealed class InMemoryEphemeralRendezvousStore : IEphemeralRendezvousSto
}
public Guid InstanceId { get; }
internal long MaintenanceSweepCount => Interlocked.Read(ref _maintenanceSweepCount);
public bool IsAvailable
{
@@ -270,6 +274,7 @@ internal sealed class InMemoryEphemeralRendezvousStore : IEphemeralRendezvousSto
if (!_presenceHandles.TryGetValue(command.Handle, out SessionListingId listingId)
|| !_listings.TryGetValue(listingId, out ListingEntry? entry)
|| entry.LeaseDeadline <= now
|| entry.Definition.HostPresenceFingerprint != command.CapabilityFingerprint)
{
return new(StoreResultCode.NotFound);
@@ -285,7 +290,7 @@ internal sealed class InMemoryEphemeralRendezvousStore : IEphemeralRendezvousSto
command.LocalEndpoint,
now + _options.PresenceLifetime);
return new(StoreResultCode.Success, Snapshot(entry));
}, cancellationToken);
}, cancellationToken, eagerCleanup: false);
public StoreResult<IReadOnlyList<StoredListing>> BrowseVisibleListings(
VisibleListingQuery query,
@@ -446,13 +451,18 @@ internal sealed class InMemoryEphemeralRendezvousStore : IEphemeralRendezvousSto
return new(StoreResultCode.NotFound);
}
if (attempt.IntroductionConsumed)
{
return new(StoreResultCode.Conflict);
}
RemoveAttempt(command.AttemptId);
return new(StoreResultCode.Success, true);
}, cancellationToken);
public StoreResult<StoredJoinAttempt> BindAttemptEndpoint(
BindAttemptEndpointCommand command,
CancellationToken cancellationToken = default) => Atomic<StoredJoinAttempt>(_ =>
CancellationToken cancellationToken = default) => Atomic<StoredJoinAttempt>(now =>
{
ArgumentNullException.ThrowIfNull(command);
if (command.Handle.Value == Guid.Empty
@@ -469,7 +479,13 @@ internal sealed class InMemoryEphemeralRendezvousStore : IEphemeralRendezvousSto
}
if (!_attemptHandles.TryGetValue(command.Handle, out JoinAttemptId attemptId)
|| !_attempts.TryGetValue(attemptId, out AttemptEntry? attempt))
|| !_attempts.TryGetValue(attemptId, out AttemptEntry? attempt)
|| attempt.Deadline <= now)
{
return new(StoreResultCode.NotFound);
}
if (!HasFreshHostPresence(attempt, now))
{
return new(StoreResultCode.NotFound);
}
@@ -503,7 +519,7 @@ internal sealed class InMemoryEphemeralRendezvousStore : IEphemeralRendezvousSto
}
return new(StoreResultCode.Success, Snapshot(attempt));
}, cancellationToken);
}, cancellationToken, eagerCleanup: false);
public StoreResult<IntroductionEndpoints> ConsumeIntroduction(
MediationHandle handle,
@@ -515,7 +531,13 @@ internal sealed class InMemoryEphemeralRendezvousStore : IEphemeralRendezvousSto
}
if (!_attemptHandles.TryGetValue(handle, out JoinAttemptId attemptId)
|| !_attempts.TryGetValue(attemptId, out AttemptEntry? attempt))
|| !_attempts.TryGetValue(attemptId, out AttemptEntry? attempt)
|| attempt.Deadline <= now)
{
return new(StoreResultCode.NotFound);
}
if (!HasFreshHostPresence(attempt, now))
{
return new(StoreResultCode.NotFound);
}
@@ -540,7 +562,7 @@ internal sealed class InMemoryEphemeralRendezvousStore : IEphemeralRendezvousSto
Snapshot(attempt),
attempt.HostEndpoint,
attempt.ClientEndpoint));
}, cancellationToken);
}, cancellationToken, eagerCleanup: false);
public StoreResult<bool> ConsumeConnectionTicket(
ConsumeConnectionTicketCommand command,
@@ -687,18 +709,38 @@ internal sealed class InMemoryEphemeralRendezvousStore : IEphemeralRendezvousSto
}
}
private StoreResult<T> Atomic<T>(Func<TimeSpan, StoreResult<T>> operation, CancellationToken cancellationToken)
private StoreResult<T> Atomic<T>(
Func<TimeSpan, StoreResult<T>> operation,
CancellationToken cancellationToken,
bool eagerCleanup = true)
{
cancellationToken.ThrowIfCancellationRequested();
lock (_gate)
{
cancellationToken.ThrowIfCancellationRequested();
TimeSpan now = _monotonicClock.Elapsed;
Cleanup(now);
// Authenticated UDP duplicates need O(1) store work. Their operations
// check exact resource deadlines and amortize physical expiry removal.
bool drainExpired = _drainDeadline is TimeSpan drainDeadline
&& now >= drainDeadline;
if (drainExpired || eagerCleanup || now >= _nextUdpMaintenance)
{
Cleanup(now);
_nextUdpMaintenance = now + UdpMaintenanceInterval;
}
return operation(now);
}
}
private bool HasFreshHostPresence(AttemptEntry attempt, TimeSpan now) =>
_listings.TryGetValue(attempt.Command.ListingId, out ListingEntry? listing)
&& listing.LeaseDeadline > now
&& _presence.TryGetValue(
listing.Definition.HostPresenceHandle,
out PresenceEntry? presence)
&& presence.Deadline > now;
private StoreResult<T>? CheckNewWorkAdmission<T>(string subject)
{
if (!_available)
@@ -718,6 +760,7 @@ internal sealed class InMemoryEphemeralRendezvousStore : IEphemeralRendezvousSto
private void Cleanup(TimeSpan now)
{
_maintenanceSweepCount++;
if (_drainDeadline is TimeSpan drainDeadline && now >= drainDeadline)
{
ClearActiveState();