Remove IP addresses from game tokens and matchmaking

This commit is contained in:
sudokoko 2024-03-17 21:41:10 -04:00
commit 5283001511
No known key found for this signature in database
GPG key ID: 248D68C664937395
13 changed files with 44 additions and 73 deletions

View file

@ -72,7 +72,7 @@ public class LoginController : ControllerBase
switch (npTicket.Platform) switch (npTicket.Platform)
{ {
case Platform.RPCS3: case Platform.RPCS3:
user = await this.database.Users.FirstOrDefaultAsync(u => u.LinkedRpcnId == npTicket.UserId); user = await this.database.Users.FirstOrDefaultAsync(u => u.LinkedRpcnId == npTicket.UserId);
break; break;
case Platform.PS3: case Platform.PS3:
case Platform.Vita: case Platform.Vita:
@ -88,7 +88,7 @@ public class LoginController : ControllerBase
// If this user id hasn't been linked to any accounts // If this user id hasn't been linked to any accounts
if (user == null) if (user == null)
{ {
// Check if there is an account with that username already // Check if there is an account with that username already
UserEntity? targetUsername = await this.database.Users.FirstOrDefaultAsync(u => u.Username == npTicket.Username); UserEntity? targetUsername = await this.database.Users.FirstOrDefaultAsync(u => u.Username == npTicket.Username);
if (targetUsername != null) if (targetUsername != null)
{ {
@ -175,7 +175,7 @@ public class LoginController : ControllerBase
} }
GameTokenEntity? token = await this.database.GameTokens.Include(t => t.User) GameTokenEntity? token = await this.database.GameTokens.Include(t => t.User)
.FirstOrDefaultAsync(t => t.UserLocation == ipAddress && t.User.Username == npTicket.Username && t.TicketHash == npTicket.TicketHash); .FirstOrDefaultAsync(t => t.User.Username == npTicket.Username && t.TicketHash == npTicket.TicketHash);
if (token != null) if (token != null)
{ {

View file

@ -87,7 +87,6 @@ public class MatchController : ControllerBase
{ {
case UpdateMyPlayerData playerData: case UpdateMyPlayerData playerData:
{ {
MatchHelper.SetUserLocation(user.UserId, token.UserLocation);
Room? room = RoomHelper.FindRoomByUser(user.UserId, token.GameVersion, token.Platform, true); Room? room = RoomHelper.FindRoomByUser(user.UserId, token.GameVersion, token.Platform, true);
if (playerData.RoomState != null) if (playerData.RoomState != null)
@ -95,19 +94,13 @@ public class MatchController : ControllerBase
room.State = (RoomState)playerData.RoomState; room.State = (RoomState)playerData.RoomState;
break; break;
} }
// Check how many people are online in release builds, disabled for debug for ..well debugging.
#if DEBUG
case FindBestRoom diveInData: case FindBestRoom diveInData:
#else
case FindBestRoom diveInData when MatchHelper.UserLocations.Count > 1:
#endif
{ {
FindBestRoomResponse? response = RoomHelper.FindBestRoom(this.database, FindBestRoomResponse? response = RoomHelper.FindBestRoom(this.database,
user, user,
token.GameVersion, token.GameVersion,
diveInData.RoomSlot, diveInData.RoomSlot,
token.Platform, token.Platform);
token.UserLocation);
if (response == null) return this.NotFound(); if (response == null) return this.NotFound();
@ -117,7 +110,7 @@ public class MatchController : ControllerBase
return this.Ok($"[{{\"StatusCode\":200}},{serialized}]"); return this.Ok($"[{{\"StatusCode\":200}},{serialized}]");
} }
case CreateRoom createRoom when !MatchHelper.UserLocations.IsEmpty: case CreateRoom createRoom:
{ {
List<int> users = new(); List<int> users = new();
foreach (string playerUsername in createRoom.Players) foreach (string playerUsername in createRoom.Players)

View file

@ -62,7 +62,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.";
#if DEBUG #if DEBUG
announceText.Append("\n\n---DEBUG INFO---\n" + announceText.Append("\n\n---DEBUG INFO---\n" +
$"user.UserId: {token.UserId}\n" + $"user.UserId: {token.UserId}\n" +
$"token.UserLocation: {token.UserLocation}\n" +
$"token.GameVersion: {token.GameVersion}\n" + $"token.GameVersion: {token.GameVersion}\n" +
$"token.TicketHash: {token.TicketHash}\n" + $"token.TicketHash: {token.TicketHash}\n" +
$"token.ExpiresAt: {token.ExpiresAt.ToString()}\n" + $"token.ExpiresAt: {token.ExpiresAt.ToString()}\n" +

View file

@ -1,8 +1,5 @@
using LBPUnion.ProjectLighthouse.Database; using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Types.Users;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Servers.Website.Controllers.Debug; namespace LBPUnion.ProjectLighthouse.Servers.Website.Controllers.Debug;
@ -27,10 +24,6 @@ public class RoomVisualizerController : ControllerBase
List<int> users = await this.database.Users.OrderByDescending(_ => EF.Functions.Random()).Take(2).Select(u => u.UserId).ToListAsync(); List<int> users = await this.database.Users.OrderByDescending(_ => EF.Functions.Random()).Take(2).Select(u => u.UserId).ToListAsync();
RoomHelper.CreateRoom(users, GameVersion.LittleBigPlanet2, Platform.PS3); RoomHelper.CreateRoom(users, GameVersion.LittleBigPlanet2, Platform.PS3);
foreach (int user in users)
{
MatchHelper.SetUserLocation(user, "127.0.0.1");
}
return this.Redirect("/debug/roomVisualizer"); return this.Redirect("/debug/roomVisualizer");
#endif #endif
} }

View file

@ -17,15 +17,15 @@
<script> <script>
let shouldRefresh = true; let shouldRefresh = true;
setTimeout(() => { setTimeout(() => {
if (shouldRefresh) window.location.reload(); if (shouldRefresh) window.location.reload();
}, @(refreshSeconds * 1000)); }, @(refreshSeconds * 1000));
function stopRefreshing() { function stopRefreshing() {
shouldRefresh = false; shouldRefresh = false;
console.log("Stopped refresh"); console.log("Stopped refresh");
const stopRefreshButton = document.getElementById("stop-refresh-button"); const stopRefreshButton = document.getElementById("stop-refresh-button");
stopRefreshButton.parentElement.removeChild(stopRefreshButton); stopRefreshButton.parentElement.removeChild(stopRefreshButton);
console.log("Removed stop refresh button"); console.log("Removed stop refresh button");
@ -61,7 +61,7 @@
#nullable enable #nullable enable
if (version == GameVersion.LittleBigPlanet1 || version == GameVersion.LittleBigPlanetPSP || version == GameVersion.Unknown) continue; if (version == GameVersion.LittleBigPlanet1 || version == GameVersion.LittleBigPlanetPSP || version == GameVersion.Unknown) continue;
FindBestRoomResponse? response = RoomHelper.FindBestRoom(Database, null, version, null, null, null); FindBestRoomResponse? response = RoomHelper.FindBestRoom(Database, null, version, null, null);
string text = response == null ? "No room found." : "Room " + response.RoomId; string text = response == null ? "No room found." : "Room " + response.RoomId;
<p><b>Best room for @version.ToPrettyString()</b>: @text</p> <p><b>Best room for @version.ToPrettyString()</b>: @text</p>

View file

@ -37,7 +37,6 @@ public static class MockHelper
UserId = 1, UserId = 1,
ExpiresAt = DateTime.MaxValue, ExpiresAt = DateTime.MaxValue,
TokenId = 1, TokenId = 1,
UserLocation = "127.0.0.1",
UserToken = "unittest", UserToken = "unittest",
}; };

View file

@ -67,7 +67,6 @@ public partial class DatabaseContext
UserToken = CryptoHelper.GenerateAuthToken(), UserToken = CryptoHelper.GenerateAuthToken(),
User = user, User = user,
UserId = user.UserId, UserId = user.UserId,
UserLocation = userLocation,
GameVersion = npTicket.GameVersion, GameVersion = npTicket.GameVersion,
Platform = npTicket.Platform, Platform = npTicket.Platform,
TicketHash = npTicket.TicketHash, TicketHash = npTicket.TicketHash,

View file

@ -11,15 +11,8 @@ namespace LBPUnion.ProjectLighthouse.Helpers;
public static partial class MatchHelper public static partial class MatchHelper
{ {
public static readonly ConcurrentDictionary<int, string?> UserLocations = new();
public static readonly ConcurrentDictionary<int, List<int>?> UserRecentlyDivedIn = new(); public static readonly ConcurrentDictionary<int, List<int>?> UserRecentlyDivedIn = new();
public static void SetUserLocation(int userId, string location)
{
if (UserLocations.TryGetValue(userId, out string? _)) UserLocations.TryRemove(userId, out _);
UserLocations.TryAdd(userId, location);
}
public static void AddUserRecentlyDivedIn(int userId, int otherUserId) public static void AddUserRecentlyDivedIn(int userId, int otherUserId)
{ {
if (!UserRecentlyDivedIn.TryGetValue(userId, out List<int>? recentlyDivedIn)) UserRecentlyDivedIn.TryAdd(userId, recentlyDivedIn = new List<int>()); if (!UserRecentlyDivedIn.TryGetValue(userId, out List<int>? recentlyDivedIn)) UserRecentlyDivedIn.TryAdd(userId, recentlyDivedIn = new List<int>());

View file

@ -1,7 +1,6 @@
#nullable enable #nullable enable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -27,7 +26,7 @@ public static class RoomHelper
private static int roomIdIncrement; private static int roomIdIncrement;
internal static int RoomIdIncrement => roomIdIncrement++; internal static int RoomIdIncrement => roomIdIncrement++;
public static FindBestRoomResponse? FindBestRoom(DatabaseContext database, UserEntity? user, GameVersion roomVersion, RoomSlot? slot, Platform? platform, string? location) public static FindBestRoomResponse? FindBestRoom(DatabaseContext database, UserEntity? user, GameVersion roomVersion, RoomSlot? slot, Platform? platform)
{ {
if (roomVersion == GameVersion.LittleBigPlanet1 || roomVersion == GameVersion.LittleBigPlanetPSP) if (roomVersion == GameVersion.LittleBigPlanet1 || roomVersion == GameVersion.LittleBigPlanetPSP)
{ {
@ -61,30 +60,10 @@ public static class RoomHelper
{ {
if (user != null && MatchHelper.DidUserRecentlyDiveInWith(user.UserId, room.HostId)) continue; if (user != null && MatchHelper.DidUserRecentlyDiveInWith(user.UserId, room.HostId)) continue;
Dictionary<int, string> relevantUserLocations = new();
// Determine if all players in a room have UserLocations stored, also store the relevant userlocations while we're at it
bool allPlayersHaveLocations = room.PlayerIds.All
(
p =>
{
bool gotValue = MatchHelper.UserLocations.TryGetValue(p, out string? value);
if (gotValue && value != null) relevantUserLocations.TryAdd(p, value);
return gotValue;
}
);
// If we don't have all locations then the game won't know how to communicate. Thus, it's not a valid room.
if (!allPlayersHaveLocations) continue;
// If we got here then it should be a valid room.
FindBestRoomResponse response = new() FindBestRoomResponse response = new()
{ {
RoomId = room.RoomId, RoomId = room.RoomId,
Players = new List<Player>(), Players = new List<Player>(),
Locations = new List<string>(),
}; };
foreach (UserEntity player in room.GetPlayers(database)) foreach (UserEntity player in room.GetPlayers(database))
@ -97,8 +76,6 @@ public static class RoomHelper
User = player, User = player,
} }
); );
response.Locations.Add(relevantUserLocations.GetValueOrDefault(player.UserId)); // Already validated to exist
} }
if (user != null) if (user != null)
@ -111,8 +88,6 @@ public static class RoomHelper
} }
); );
if (location == null) response.Locations.Add(location);
response.Slots = new List<List<int>> response.Slots = new List<List<int>>
{ {
new() new()
@ -189,7 +164,7 @@ public static class RoomHelper
{ {
StorableList<Room> rooms = Rooms; // cache rooms so we dont gen a new one every time StorableList<Room> rooms = Rooms; // cache rooms so we dont gen a new one every time
List<Room> roomsToUpdate = new(); List<Room> roomsToUpdate = new();
#if DEBUG #if DEBUG
Logger.Debug($"Cleaning up rooms... (took {stopwatch.ElapsedMilliseconds}ms to get lock on {nameof(RoomLock)})", LogArea.Match); Logger.Debug($"Cleaning up rooms... (took {stopwatch.ElapsedMilliseconds}ms to get lock on {nameof(RoomLock)})", LogArea.Match);
#endif #endif
@ -205,7 +180,7 @@ public static class RoomHelper
.ToList(); .ToList();
foreach (int player in playersToRemove) room.PlayerIds.Remove(player); foreach (int player in playersToRemove) room.PlayerIds.Remove(player);
roomsToUpdate.Add(room); roomsToUpdate.Add(room);
} }
@ -248,7 +223,7 @@ public static class RoomHelper
int roomCountAfterCleanup = rooms.Count(); int roomCountAfterCleanup = rooms.Count();
// Log the amount of rooms cleaned up. // Log the amount of rooms cleaned up.
// If we didnt clean any rooms, it's not useful to log in a // If we didnt clean any rooms, it's not useful to log in a
// production environment but it's still quite useful for debugging. // production environment but it's still quite useful for debugging.
// //
// So, we handle that case here: // So, we handle that case here:

View file

@ -0,0 +1,30 @@
using LBPUnion.ProjectLighthouse.Database;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace LBPUnion.ProjectLighthouse.Migrations
{
[DbContext(typeof(DatabaseContext))]
[Migration("20240317231145_RemoveUserLocationFromGameTokens")]
public partial class RemoveUserLocationFromGameTokens : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "UserLocation",
table: "GameTokens");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "UserLocation",
table: "GameTokens",
type: "longtext",
nullable: true)
.Annotation("MySql:CharSet", "utf8mb4");
}
}
}

View file

@ -16,7 +16,7 @@ namespace ProjectLighthouse.Migrations
{ {
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder modelBuilder
.HasAnnotation("ProductVersion", "7.0.13") .HasAnnotation("ProductVersion", "8.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 64); .HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Interaction.HeartedLevelEntity", b => modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Interaction.HeartedLevelEntity", b =>
@ -995,9 +995,6 @@ namespace ProjectLighthouse.Migrations
b.Property<int>("UserId") b.Property<int>("UserId")
.HasColumnType("int"); .HasColumnType("int");
b.Property<string>("UserLocation")
.HasColumnType("longtext");
b.Property<string>("UserToken") b.Property<string>("UserToken")
.HasColumnType("longtext"); .HasColumnType("longtext");

View file

@ -19,8 +19,6 @@ public class GameTokenEntity
public string UserToken { get; set; } public string UserToken { get; set; }
public string UserLocation { get; set; }
public GameVersion GameVersion { get; set; } public GameVersion GameVersion { get; set; }
public Platform Platform { get; set; } public Platform Platform { get; set; }

View file

@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace LBPUnion.ProjectLighthouse.Types.Matchmaking.Rooms; namespace LBPUnion.ProjectLighthouse.Types.Matchmaking.Rooms;
@ -14,8 +13,4 @@ public class FindBestRoomResponse
[JsonIgnore] [JsonIgnore]
public IEnumerable<int> FirstSlot => this.Slots[0]; public IEnumerable<int> FirstSlot => this.Slots[0];
[JsonPropertyName("Location")]
[SuppressMessage("ReSharper", "CollectionNeverQueried.Global")]
public List<string> Locations { get; set; }
} }