feat: implement scoped join attempts and tickets (#10)
quality-gate / quality (push) Successful in 1m1s
quality-gate / quality (push) Successful in 1m1s
Closes #10
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
using System.Net;
|
||||
using FinalFactory.Rendezvous.Contracts;
|
||||
using FinalFactory.Rendezvous.Server.JoinAttempts;
|
||||
using FinalFactory.Rendezvous.Server.Provisioning;
|
||||
using FinalFactory.Rendezvous.Server.State;
|
||||
using FinalFactory.Rendezvous.Tests.Provisioning;
|
||||
using FinalFactory.Rendezvous.Tests.Sessions;
|
||||
|
||||
namespace FinalFactory.Rendezvous.Tests.JoinAttempts;
|
||||
|
||||
internal sealed class JoinAttemptFixture : IDisposable
|
||||
{
|
||||
private int _sequence;
|
||||
|
||||
public JoinAttemptFixture(EphemeralStoreOptions? options = null)
|
||||
{
|
||||
Sessions = new(options);
|
||||
Cursors = new();
|
||||
GamePolicyRegistry policies = GamePolicyRegistry.Create([ProvisioningTestData.CreatePolicy()]);
|
||||
Service = new(policies, Sessions.Store, Sessions.Capabilities, Cursors, Sessions.Clock);
|
||||
ClientSubject = Service.CreateAnonymousClientSubject(IPAddress.Parse("198.51.100.40"));
|
||||
}
|
||||
|
||||
public SessionLeaseFixture Sessions { get; }
|
||||
public JoinAttemptCursorCodec Cursors { get; }
|
||||
public JoinAttemptService Service { get; }
|
||||
public string ClientSubject { get; }
|
||||
|
||||
public (RegisterSessionResponse Registration, StoredListing Listing) CreateHost(bool bindPresence = true)
|
||||
{
|
||||
RegisterSessionResponse registration = Sessions.Register();
|
||||
if (bindPresence)
|
||||
{
|
||||
Assert.True(Sessions.BindPresence(registration).Succeeded);
|
||||
}
|
||||
|
||||
StoredListing listing = Sessions.Store.GetListing(registration.ListingId, false).Value!;
|
||||
return (registration, listing);
|
||||
}
|
||||
|
||||
public CreateJoinAttemptRequest Request(
|
||||
SessionListingId listingId,
|
||||
string? idempotencyKey = null) => new()
|
||||
{
|
||||
IdempotencyKey = idempotencyKey ?? $"join-{Interlocked.Increment(ref _sequence)}",
|
||||
GameId = Sessions.Scope.GameId,
|
||||
EnvironmentId = Sessions.Scope.EnvironmentId,
|
||||
ListingId = listingId,
|
||||
ProtocolVersion = 7,
|
||||
};
|
||||
|
||||
public CreateJoinAttemptResponse Create(
|
||||
SessionListingId listingId,
|
||||
string? idempotencyKey = null)
|
||||
{
|
||||
JoinAttemptServiceResult<CreateJoinAttemptResponse> result = Service.Create(
|
||||
ClientSubject,
|
||||
Request(listingId, idempotencyKey));
|
||||
Assert.True(result.Succeeded);
|
||||
return Assert.IsType<CreateJoinAttemptResponse>(result.Value);
|
||||
}
|
||||
|
||||
public StoredJoinAttempt GetAttempt(
|
||||
RegisterSessionResponse registration,
|
||||
JoinAttemptId attemptId)
|
||||
{
|
||||
Assert.True(Sessions.Capabilities.TryFingerprint(
|
||||
registration.LeaseToken,
|
||||
out SecretFingerprint leaseFingerprint));
|
||||
IReadOnlyList<StoredJoinAttempt> attempts = Sessions.Store.BrowseHostJoinAttempts(new(
|
||||
registration.ListingId,
|
||||
leaseFingerprint,
|
||||
ContractLimits.BrowserPageMaxItems)).Value!;
|
||||
return attempts.Single(attempt => attempt.AttemptId == attemptId);
|
||||
}
|
||||
|
||||
public IntroductionEndpoints Introduce(
|
||||
RegisterSessionResponse registration,
|
||||
CreateJoinAttemptResponse created)
|
||||
{
|
||||
StoredJoinAttempt attempt = GetAttempt(registration, created.AttemptId);
|
||||
HostJoinAttempt host = Service.BrowseForHost(
|
||||
registration.ListingId,
|
||||
ContractLimits.ContractVersion,
|
||||
registration.LeaseToken,
|
||||
ContractLimits.BrowserPageMaxItems,
|
||||
null).Value!.Items.Single(item => item.AttemptId == created.AttemptId);
|
||||
Assert.True(Sessions.Capabilities.TryFingerprint(
|
||||
host.HostPunchCapability,
|
||||
out SecretFingerprint hostFingerprint));
|
||||
Assert.True(Sessions.Capabilities.TryFingerprint(
|
||||
created.ClientPunchCapability,
|
||||
out SecretFingerprint clientFingerprint));
|
||||
Assert.True(Sessions.Store.BindAttemptEndpoint(new(
|
||||
attempt.MediationHandle,
|
||||
AttemptPeerRole.Host,
|
||||
hostFingerprint,
|
||||
new(AddressFamilyKind.Ipv4, "203.0.113.20", 41_000),
|
||||
null)).Succeeded);
|
||||
Assert.True(Sessions.Store.BindAttemptEndpoint(new(
|
||||
attempt.MediationHandle,
|
||||
AttemptPeerRole.Client,
|
||||
clientFingerprint,
|
||||
new(AddressFamilyKind.Ipv4, "198.51.100.40", 42_000),
|
||||
null)).Succeeded);
|
||||
StoreResult<IntroductionEndpoints> introduced = Sessions.Store.ConsumeIntroduction(
|
||||
attempt.MediationHandle);
|
||||
Assert.True(introduced.Succeeded);
|
||||
return introduced.Value!;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Cursors.Dispose();
|
||||
Sessions.Dispose();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user