1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-20 06:39:54 +08:00

Always use MessagePack to talk to spectator server

This commit is contained in:
Dan Balasescu
2025-08-06 16:11:17 +09:00
Unverified
parent 8b2e394509
commit d0e9fda874
7 changed files with 9 additions and 94 deletions
+2 -2
View File
@@ -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);
+1 -1
View File
@@ -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);
+1 -2
View File
@@ -138,8 +138,7 @@ namespace osu.Game.Online.API
/// </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>
/// <param name="preferMessagePack">Whether to use MessagePack for serialisation if available on this platform.</param>
IHubClientConnector? GetHubConnector(string clientName, string endpoint, bool preferMessagePack = true);
IHubClientConnector? GetHubConnector(string clientName, string endpoint);
/// <summary>
/// Accesses the <see cref="INotificationsClient"/> used to receive asynchronous notifications from web.
+4 -26
View File
@@ -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;
/// <summary>
/// The current connection opened by this connector.
@@ -43,14 +39,12 @@ namespace osu.Game.Online
/// <param name="endpoint">The endpoint to the hub.</param>
/// <param name="api"> An API provider used to react to connection state changes.</param>
/// <param name="versionHash">The hash representing the current game version, used for verification purposes.</param>
/// <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)
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<JsonConverter>
{
new SignalRDerivedTypeWorkaroundJsonConverter(),
};
});
}
options.SerializerOptions = SignalRUnionWorkaroundResolver.OPTIONS;
});
var newConnection = builder.Build();
@@ -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)
{
@@ -1,61 +0,0 @@
// 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;
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) =>
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();
}
}
}
@@ -14,7 +14,6 @@ namespace osu.Game.Online
/// A static class providing the list of types requiring workarounds for serialisation in SignalR.
/// </summary>
/// <seealso cref="SignalRUnionWorkaroundResolver"/>
/// <seealso cref="SignalRDerivedTypeWorkaroundJsonConverter"/>
internal static class SignalRWorkaroundTypes
{
internal static readonly IReadOnlyList<(Type derivedType, Type baseType)> BASE_TYPE_MAPPING = new[]