2021-02-09 06:52:35 +08:00
|
|
|
// 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.
|
|
|
|
|
|
|
|
using System;
|
2021-11-11 13:04:17 +08:00
|
|
|
using System.Collections.Generic;
|
2022-04-21 14:16:39 +08:00
|
|
|
using System.Net;
|
2022-12-14 22:01:05 +08:00
|
|
|
using System.Runtime.CompilerServices;
|
2021-02-09 06:52:35 +08:00
|
|
|
using System.Threading;
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
using Microsoft.AspNetCore.SignalR.Client;
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
using osu.Framework;
|
|
|
|
using osu.Game.Online.API;
|
|
|
|
|
|
|
|
namespace osu.Game.Online
|
|
|
|
{
|
2022-11-02 10:43:22 +08:00
|
|
|
public class HubClientConnector : PersistentEndpointClientConnector, IHubClientConnector
|
2021-02-09 06:52:35 +08:00
|
|
|
{
|
2022-05-26 17:03:41 +08:00
|
|
|
public const string SERVER_SHUTDOWN_MESSAGE = "Server is shutting down.";
|
|
|
|
|
2021-02-09 06:52:35 +08:00
|
|
|
/// <summary>
|
2021-02-11 17:39:06 +08:00
|
|
|
/// Invoked whenever a new hub connection is built, to configure it before it's started.
|
2021-02-09 06:52:35 +08:00
|
|
|
/// </summary>
|
2021-02-15 15:31:00 +08:00
|
|
|
public Action<HubConnection>? ConfigureConnection { get; set; }
|
2021-02-09 06:52:35 +08:00
|
|
|
|
|
|
|
private readonly string endpoint;
|
2021-02-14 22:31:57 +08:00
|
|
|
private readonly string versionHash;
|
2021-08-02 13:44:51 +08:00
|
|
|
private readonly bool preferMessagePack;
|
2021-02-11 17:32:54 +08:00
|
|
|
private readonly IAPIProvider api;
|
2021-02-09 06:52:35 +08:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The current connection opened by this connector.
|
|
|
|
/// </summary>
|
2022-10-27 13:34:24 +08:00
|
|
|
public new HubConnection? CurrentConnection => ((HubClient?)base.CurrentConnection)?.Connection;
|
2021-02-09 06:52:35 +08:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Constructs a new <see cref="HubClientConnector"/>.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="clientName">The name of the client this connector connects for, used for logging.</param>
|
|
|
|
/// <param name="endpoint">The endpoint to the hub.</param>
|
2021-02-11 17:32:54 +08:00
|
|
|
/// <param name="api"> An API provider used to react to connection state changes.</param>
|
2021-02-14 22:31:57 +08:00
|
|
|
/// <param name="versionHash">The hash representing the current game version, used for verification purposes.</param>
|
2021-08-02 13:44:51 +08:00
|
|
|
/// <param name="preferMessagePack">Whether to use MessagePack for serialisation if available on this platform.</param>
|
|
|
|
public HubClientConnector(string clientName, string endpoint, IAPIProvider api, string versionHash, bool preferMessagePack = true)
|
2022-10-27 13:34:24 +08:00
|
|
|
: base(api)
|
2021-02-09 06:52:35 +08:00
|
|
|
{
|
2022-10-27 13:34:24 +08:00
|
|
|
ClientName = clientName;
|
2021-02-09 06:52:35 +08:00
|
|
|
this.endpoint = endpoint;
|
2021-02-09 12:53:22 +08:00
|
|
|
this.api = api;
|
2021-02-14 22:31:57 +08:00
|
|
|
this.versionHash = versionHash;
|
2021-08-02 13:44:51 +08:00
|
|
|
this.preferMessagePack = preferMessagePack;
|
2022-11-04 18:36:24 +08:00
|
|
|
|
|
|
|
// Automatically start these connections.
|
|
|
|
Start();
|
2021-07-28 19:46:02 +08:00
|
|
|
}
|
|
|
|
|
2022-11-02 10:43:22 +08:00
|
|
|
protected override Task<PersistentEndpointClient> BuildConnectionAsync(CancellationToken cancellationToken)
|
2021-02-09 06:52:35 +08:00
|
|
|
{
|
|
|
|
var builder = new HubConnectionBuilder()
|
2021-02-14 22:31:57 +08:00
|
|
|
.WithUrl(endpoint, options =>
|
|
|
|
{
|
2022-12-12 06:30:49 +08:00
|
|
|
// Configuring proxies is not supported on iOS, see https://github.com/xamarin/xamarin-macios/issues/14632.
|
|
|
|
if (RuntimeInfo.OS != RuntimeInfo.Platform.iOS)
|
|
|
|
{
|
|
|
|
// Use HttpClient.DefaultProxy once on net6 everywhere.
|
|
|
|
// The credential setter can also be removed at this point.
|
|
|
|
options.Proxy = WebRequest.DefaultWebProxy;
|
|
|
|
if (options.Proxy != null)
|
|
|
|
options.Proxy.Credentials = CredentialCache.DefaultCredentials;
|
|
|
|
}
|
2022-04-21 14:16:39 +08:00
|
|
|
|
2021-02-14 22:31:57 +08:00
|
|
|
options.Headers.Add("Authorization", $"Bearer {api.AccessToken}");
|
|
|
|
options.Headers.Add("OsuVersionHash", versionHash);
|
|
|
|
});
|
2021-02-09 06:52:35 +08:00
|
|
|
|
2022-12-14 22:01:05 +08:00
|
|
|
if (RuntimeFeature.IsDynamicCodeCompiled && preferMessagePack)
|
2021-08-19 16:41:50 +08:00
|
|
|
{
|
|
|
|
builder.AddMessagePackProtocol(options =>
|
|
|
|
{
|
|
|
|
options.SerializerOptions = SignalRUnionWorkaroundResolver.OPTIONS;
|
|
|
|
});
|
|
|
|
}
|
2021-02-09 06:52:35 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// eventually we will precompile resolvers for messagepack, but this isn't working currently
|
|
|
|
// see https://github.com/neuecc/MessagePack-CSharp/issues/780#issuecomment-768794308.
|
2021-08-02 13:37:47 +08:00
|
|
|
builder.AddNewtonsoftJsonProtocol(options =>
|
|
|
|
{
|
|
|
|
options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
|
2021-11-11 13:04:17 +08:00
|
|
|
options.PayloadSerializerSettings.Converters = new List<JsonConverter>
|
|
|
|
{
|
|
|
|
new SignalRDerivedTypeWorkaroundJsonConverter(),
|
|
|
|
};
|
2021-08-02 13:37:47 +08:00
|
|
|
});
|
2021-02-09 06:52:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
var newConnection = builder.Build();
|
|
|
|
|
2021-02-11 15:49:16 +08:00
|
|
|
ConfigureConnection?.Invoke(newConnection);
|
2021-02-09 06:52:35 +08:00
|
|
|
|
2022-11-02 10:43:22 +08:00
|
|
|
return Task.FromResult((PersistentEndpointClient)new HubClient(newConnection));
|
2021-02-11 15:49:16 +08:00
|
|
|
}
|
2021-02-09 06:52:35 +08:00
|
|
|
|
2022-10-27 13:34:24 +08:00
|
|
|
protected override string ClientName { get; }
|
2021-02-09 06:52:35 +08:00
|
|
|
}
|
|
|
|
}
|