Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 48 additions & 5 deletions osu.Game/Online/API/APIAccess.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

#nullable disable
Expand Down Expand Up @@ -38,6 +38,7 @@ public partial class APIAccess : CompositeComponent, IAPIProvider
private readonly OAuth authentication;

private readonly Queue<APIRequest> queue = new Queue<APIRequest>();
private readonly AutoResetEvent updateEvent = new AutoResetEvent(true);

public EndpointConfiguration Endpoints { get; }

Expand Down Expand Up @@ -70,6 +71,7 @@ public partial class APIAccess : CompositeComponent, IAPIProvider

private readonly CancellationTokenSource cancellationToken = new CancellationTokenSource();
private readonly Logger log;
private readonly WaitHandle[] waitHandles;

public APIAccess(OsuGameBase game, OsuConfigManager config, EndpointConfiguration endpoints, string versionHash)
{
Expand Down Expand Up @@ -98,6 +100,7 @@ public APIAccess(OsuGameBase game, OsuConfigManager config, EndpointConfiguratio

authentication.TokenString = config.Get<string>(OsuSetting.Token);
authentication.Token.ValueChanged += onTokenChanged;
authentication.Token.BindValueChanged(_ => updateEvent.Set());

AddInternal(localUserState = new LocalUserState(this, config));

Expand All @@ -110,6 +113,9 @@ public APIAccess(OsuGameBase game, OsuConfigManager config, EndpointConfiguratio
state.Value = APIState.Connecting;
}

waitHandles = new[] { updateEvent, cancellationToken.Token.WaitHandle };
state.BindValueChanged(_ => updateEvent.Set());

var thread = new Thread(run)
{
Name = "APIAccess",
Expand Down Expand Up @@ -168,15 +174,30 @@ private void run()
// To recover from a failing state, falling through and running the full reconnection process seems safest for now.
// This could probably be replaced with a ping-style request if we want to avoid the reconnection overheads.
log.Add($@"{nameof(APIAccess)} is in a failing state, waiting a bit before we try again...");
Thread.Sleep(5000);

try
{
WaitHandle.WaitAny(waitHandles, 5000);
}
catch (Exception)
{
}
}

// Ensure that we have valid credentials.
// If not, setting the offline state will allow the game to prompt the user to provide new credentials.
if (!HasLogin)
{
state.Value = APIState.Offline;
Thread.Sleep(50);

try
{
WaitHandle.WaitAny(waitHandles);
}
catch (Exception)
{
}

continue;
}

Expand All @@ -189,7 +210,14 @@ private void run()

if (state.Value != APIState.Online)
{
Thread.Sleep(50);
try
{
WaitHandle.WaitAny(waitHandles);
}
catch (Exception)
{
}

continue;
}
}
Expand All @@ -202,7 +230,14 @@ private void run()
}

processQueuedRequests();
Thread.Sleep(50);

try
{
WaitHandle.WaitAny(waitHandles);
}
catch (Exception)
{
}
}
}

Expand Down Expand Up @@ -384,13 +419,15 @@ public void Login(string username, string password)

ProvidedUsername = username;
this.password = password;
updateEvent.Set();
}

public void AuthenticateSecondFactor(string code)
{
Debug.Assert(State.Value == APIState.RequiresSecondFactorAuth);

SecondFactorCode = code;
updateEvent.Set();
}

public IHubClientConnector GetHubConnector(string clientName, string endpoint) =>
Expand Down Expand Up @@ -564,6 +601,7 @@ public void Queue(APIRequest request)
}

queue.Enqueue(request);
updateEvent.Set();
}
}

Expand All @@ -580,6 +618,8 @@ private void flushQueue(bool failOldRequests = true)
foreach (var req in oldQueueRequests)
req.Fail(new WebRequestFlushedException(state.Value));
}

updateEvent.Set();
}
}

Expand All @@ -600,7 +640,10 @@ protected override void Dispose(bool isDisposing)
base.Dispose(isDisposing);

flushQueue();

cancellationToken.Cancel();
cancellationToken.Dispose();
updateEvent.Dispose();
}

internal class WebRequestFlushedException : Exception
Expand Down