diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 525eb98a86..54eed58c13 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -409,8 +409,8 @@ namespace osu.Game.Online.API SecondFactorCode = code; } - public IHubClientConnector GetHubConnector(string clientName, string endpoint, bool preferMessagePack) => - new HubClientConnector(clientName, endpoint, this, versionHash, preferMessagePack); + public IHubClientConnector GetHubConnector(string clientName, string endpoint) => + new HubClientConnector(clientName, endpoint, this, versionHash); public IChatClient GetChatClient() => new WebSocketChatClient(this); diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index 0c2ed9903c..74e0ca2873 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -185,7 +185,7 @@ namespace osu.Game.Online.API { } - public IHubClientConnector? GetHubConnector(string clientName, string endpoint, bool preferMessagePack) => null; + public IHubClientConnector? GetHubConnector(string clientName, string endpoint) => null; public IChatClient GetChatClient() => new TestChatClientConnector(this); diff --git a/osu.Game/Online/API/IAPIProvider.cs b/osu.Game/Online/API/IAPIProvider.cs index 3ab985e41f..2634ea137f 100644 --- a/osu.Game/Online/API/IAPIProvider.cs +++ b/osu.Game/Online/API/IAPIProvider.cs @@ -138,8 +138,7 @@ namespace osu.Game.Online.API /// /// The name of the client this connector connects for, used for logging. /// The endpoint to the hub. - /// Whether to use MessagePack for serialisation if available on this platform. - IHubClientConnector? GetHubConnector(string clientName, string endpoint, bool preferMessagePack = true); + IHubClientConnector? GetHubConnector(string clientName, string endpoint); /// /// Accesses the used to receive asynchronous notifications from web. diff --git a/osu.Game/Online/HubClientConnector.cs b/osu.Game/Online/HubClientConnector.cs index 9288a32052..e6391e8810 100644 --- a/osu.Game/Online/HubClientConnector.cs +++ b/osu.Game/Online/HubClientConnector.cs @@ -2,14 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Net; -using System.Runtime.CompilerServices; 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; @@ -29,7 +26,6 @@ namespace osu.Game.Online private readonly string endpoint; private readonly string versionHash; - private readonly bool preferMessagePack; /// /// The current connection opened by this connector. @@ -43,14 +39,12 @@ namespace osu.Game.Online /// The endpoint to the hub. /// An API provider used to react to connection state changes. /// The hash representing the current game version, used for verification purposes. - /// Whether to use MessagePack for serialisation if available on this platform. - public HubClientConnector(string clientName, string endpoint, IAPIProvider api, string versionHash, bool preferMessagePack = true) + public HubClientConnector(string clientName, string endpoint, IAPIProvider api, string versionHash) : base(api) { ClientName = clientName; this.endpoint = endpoint; this.versionHash = versionHash; - this.preferMessagePack = preferMessagePack; // Automatically start these connections. Start(); @@ -78,26 +72,10 @@ namespace osu.Game.Online options.Headers.Add(CLIENT_SESSION_ID_HEADER, API.SessionIdentifier.ToString()); }); - if (RuntimeFeature.IsDynamicCodeCompiled && preferMessagePack) + builder.AddMessagePackProtocol(options => { - builder.AddMessagePackProtocol(options => - { - options.SerializerOptions = SignalRUnionWorkaroundResolver.OPTIONS; - }); - } - 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. - builder.AddNewtonsoftJsonProtocol(options => - { - options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; - options.PayloadSerializerSettings.Converters = new List - { - new SignalRDerivedTypeWorkaroundJsonConverter(), - }; - }); - } + options.SerializerOptions = SignalRUnionWorkaroundResolver.OPTIONS; + }); var newConnection = builder.Build(); diff --git a/osu.Game/Online/Metadata/OnlineMetadataClient.cs b/osu.Game/Online/Metadata/OnlineMetadataClient.cs index 366ad70db2..6402962e85 100644 --- a/osu.Game/Online/Metadata/OnlineMetadataClient.cs +++ b/osu.Game/Online/Metadata/OnlineMetadataClient.cs @@ -56,7 +56,7 @@ namespace osu.Game.Online.Metadata { // Importantly, we are intentionally not using MessagePack here to correctly support derived class serialization. // More information on the limitations / reasoning can be found in osu-server-spectator's initialisation code. - connector = api.GetHubConnector(nameof(OnlineMetadataClient), endpoint, false); + connector = api.GetHubConnector(nameof(OnlineMetadataClient), endpoint); if (connector != null) { diff --git a/osu.Game/Online/SignalRDerivedTypeWorkaroundJsonConverter.cs b/osu.Game/Online/SignalRDerivedTypeWorkaroundJsonConverter.cs deleted file mode 100644 index 86708bee82..0000000000 --- a/osu.Game/Online/SignalRDerivedTypeWorkaroundJsonConverter.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using System.Linq; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace osu.Game.Online -{ - /// - /// A type of that serializes a subset of types used in multiplayer/spectator communication that - /// derive from a known base type. This is a safe alternative to using or , - /// which are known to have security issues. - /// - public class SignalRDerivedTypeWorkaroundJsonConverter : JsonConverter - { - public override bool CanConvert(Type objectType) => - SignalRWorkaroundTypes.BASE_TYPE_MAPPING.Any(t => - objectType == t.baseType || - objectType == t.derivedType); - - public override object? ReadJson(JsonReader reader, Type objectType, object? o, JsonSerializer jsonSerializer) - { - if (reader.TokenType == JsonToken.Null) - return null; - - JObject obj = JObject.Load(reader); - - string type = (string)obj[@"$dtype"]!; - - var resolvedType = SignalRWorkaroundTypes.BASE_TYPE_MAPPING.Select(t => t.derivedType).Single(t => t.Name == type); - - object? instance = Activator.CreateInstance(resolvedType); - - if (instance != null) - jsonSerializer.Populate(obj["$value"]!.CreateReader(), instance); - - return instance; - } - - public override void WriteJson(JsonWriter writer, object? o, JsonSerializer serializer) - { - if (o == null) - { - writer.WriteNull(); - return; - } - - writer.WriteStartObject(); - - writer.WritePropertyName(@"$dtype"); - serializer.Serialize(writer, o.GetType().Name); - - writer.WritePropertyName(@"$value"); - writer.WriteRawValue(JsonConvert.SerializeObject(o)); - - writer.WriteEndObject(); - } - } -} diff --git a/osu.Game/Online/SignalRWorkaroundTypes.cs b/osu.Game/Online/SignalRWorkaroundTypes.cs index 757bb07ec8..6ae178e04c 100644 --- a/osu.Game/Online/SignalRWorkaroundTypes.cs +++ b/osu.Game/Online/SignalRWorkaroundTypes.cs @@ -14,7 +14,6 @@ namespace osu.Game.Online /// A static class providing the list of types requiring workarounds for serialisation in SignalR. /// /// - /// internal static class SignalRWorkaroundTypes { internal static readonly IReadOnlyList<(Type derivedType, Type baseType)> BASE_TYPE_MAPPING = new[]