Skip to content

Commit

Permalink
MatchingEndpoints: Fixup corrupted strings sent by the game.
Browse files Browse the repository at this point in the history
LBP2 for some reason like to send "null" `Location` items, which look like `"0.0.0.0"`.

While this isn't directly a problem, a bug in the serialization code causes the character *after* the null location to be corrupted, eg. `"0.0.0.0","1.1.1.1"` gets corrupted into `"0.0.0.0""1.1.1.1"`, and `"0.0.0.0"],"` gets corrupted into `"0.0.0.0","`. Both of these cases are invalid JSON syntax and a problem.

To fix this issue, I iterate over the match body sent, and find the any instances of `"0.0.0.0"`, I then check what character is *after* the null string, if it is a `"`, then I know that it has corrupted a `,`, since the only times a quote will be after that, is if another string is meant to be in the array. If the next character is `,`, then I know that it has corrupted a `]`, since the only time there will ever be a `,` two characters after a null location, is when the array has been closed.

By inserting these corrupted characters back into the string, it restores the string to the intended value.
  • Loading branch information
Beyley committed Jul 28, 2024
1 parent a2d8ff1 commit 2e2861d
Showing 1 changed file with 55 additions and 2 deletions.
57 changes: 55 additions & 2 deletions Refresh.GameServer/Endpoints/Game/MatchingEndpoints.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Text;
using Bunkum.Core;
using Bunkum.Core.Endpoints;
using Bunkum.Core.Endpoints.Debugging;
Expand All @@ -14,6 +15,55 @@ namespace Refresh.GameServer.Endpoints.Game;

public class MatchingEndpoints : EndpointGroup
{
public static string FixupLocationData(string body)
{
StringBuilder jsonBodyBuilder = new();

const string locationStart = "\"Location\":[";
const string corruptedStr = "\"0.0.0.0\"";

int locationIndex = body.IndexOf(locationStart, StringComparison.InvariantCulture) + locationStart.Length;
// Append the start of the "location" mess
jsonBodyBuilder.Append(body.AsSpan()[..locationIndex]);
ReadOnlySpan<char> pastLocationStart = body.AsSpan()[locationIndex..];

for (int i = 0; i < pastLocationStart.Length;)
{
ReadOnlySpan<char> slice = pastLocationStart[i..];

int corruptedStart = slice.IndexOf(corruptedStr);
// If theres no more corrupted strings, then we are done fixing it up
if (corruptedStart == -1)
{
jsonBodyBuilder.Append(slice);
break;
}

int corruptedEnd = corruptedStart + corruptedStr.Length;
char charAfterCorruption = slice[corruptedEnd];

switch (charAfterCorruption)
{
// If this is the start to a string, then we know that a `,` was corrupted
case '\"':
jsonBodyBuilder.Append(slice[..corruptedEnd]);
jsonBodyBuilder.Append(',');
i += corruptedEnd;
continue;
// If this is a comma, then we know that a ']' was corrupted
case ',':
jsonBodyBuilder.Append(slice[..corruptedEnd]);
jsonBodyBuilder.Append(']');
i += corruptedEnd;
continue;
}

i++;
}

return jsonBodyBuilder.ToString();
}

// [FindBestRoom,["Players":["VitaGamer128"],"Reservations":["0"],"NAT":[2],"Slots":[[5,0]],"Location":[0x17257bc9,0x17257bf2],"Language":1,"BuildVersion":289,"Search":"","RoomState":3]]
[GameEndpoint("match", HttpMethods.Post, ContentType.Json)]
[DebugRequestBody, DebugResponseBody]
Expand All @@ -24,9 +74,12 @@ public Response Match(
DataContext dataContext,
GameServerConfig gameServerConfig)
{
(string method, string jsonBody) = MatchService.ExtractMethodAndBodyFromJson(body);
(string method, string rawJsonBody) = MatchService.ExtractMethodAndBodyFromJson(body);

string jsonBody = FixupLocationData(rawJsonBody);

context.Logger.LogInfo(BunkumCategory.Matching, $"Received {method} match request, data: {jsonBody}");

JsonSerializer serializer = new();
using StringReader reader = new(jsonBody);
using JsonTextReader jsonReader = new(reader);
Expand Down

0 comments on commit 2e2861d

Please sign in to comment.