mirror of
https://github.com/ppy/osu.git
synced 2025-01-13 07:22:54 +08:00
Replace usage of TypeNameHandling.All
with custom type converter
This commit is contained in:
parent
16418ac2ab
commit
98fa253e1e
@ -4,6 +4,7 @@
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
@ -161,9 +162,10 @@ namespace osu.Game.Online
|
||||
builder.AddNewtonsoftJsonProtocol(options =>
|
||||
{
|
||||
options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
|
||||
// TODO: This should only be required to be `TypeNameHandling.Auto`.
|
||||
// See usage in osu-server-spectator for further documentation as to why this is required.
|
||||
options.PayloadSerializerSettings.TypeNameHandling = TypeNameHandling.All;
|
||||
options.PayloadSerializerSettings.Converters = new List<JsonConverter>
|
||||
{
|
||||
new SignalRDerivedTypeWorkaroundJsonConverter(),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
60
osu.Game/Online/SignalRDerivedTypeWorkaroundJsonConverter.cs
Normal file
60
osu.Game/Online/SignalRDerivedTypeWorkaroundJsonConverter.cs
Normal file
@ -0,0 +1,60 @@
|
||||
// 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 enable
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace osu.Game.Online
|
||||
{
|
||||
/// <summary>
|
||||
/// A type of <see cref="JsonConverter"/> 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 <see cref="TypeNameHandling.Auto"/> or <see cref="TypeNameHandling.All"/>,
|
||||
/// which are known to have security issues.
|
||||
/// </summary>
|
||||
public class SignalRDerivedTypeWorkaroundJsonConverter : JsonConverter
|
||||
{
|
||||
public override bool CanConvert(Type objectType) =>
|
||||
SignalRUnionWorkaroundResolver.BASE_TYPES.Contains(objectType) ||
|
||||
SignalRUnionWorkaroundResolver.DERIVED_TYPES.Contains(objectType);
|
||||
|
||||
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 = SignalRUnionWorkaroundResolver.DERIVED_TYPES.Single(t => t.Name == type);
|
||||
|
||||
object? instance = Activator.CreateInstance(resolvedType);
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
@ -20,7 +20,22 @@ namespace osu.Game.Online
|
||||
public static readonly MessagePackSerializerOptions OPTIONS =
|
||||
MessagePackSerializerOptions.Standard.WithResolver(new SignalRUnionWorkaroundResolver());
|
||||
|
||||
private static readonly Dictionary<Type, IMessagePackFormatter> formatter_map = new Dictionary<Type, IMessagePackFormatter>
|
||||
public static readonly IReadOnlyList<Type> BASE_TYPES = new[]
|
||||
{
|
||||
typeof(MatchServerEvent),
|
||||
typeof(MatchUserRequest),
|
||||
typeof(MatchRoomState),
|
||||
typeof(MatchUserState),
|
||||
};
|
||||
|
||||
public static readonly IReadOnlyList<Type> DERIVED_TYPES = new[]
|
||||
{
|
||||
typeof(ChangeTeamRequest),
|
||||
typeof(TeamVersusRoomState),
|
||||
typeof(TeamVersusUserState),
|
||||
};
|
||||
|
||||
private static readonly IReadOnlyDictionary<Type, IMessagePackFormatter> formatter_map = new Dictionary<Type, IMessagePackFormatter>
|
||||
{
|
||||
{ typeof(TeamVersusUserState), new TypeRedirectingFormatter<TeamVersusUserState, MatchUserState>() },
|
||||
{ typeof(TeamVersusRoomState), new TypeRedirectingFormatter<TeamVersusRoomState, MatchRoomState>() },
|
||||
|
Loading…
Reference in New Issue
Block a user