Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -351,4 +351,4 @@ MigrationBackup/

out/
run/
/BeatTogether.MasterServer.Kernel/Properties/launchSettings.json
/BeatTogether.MasterServer/appsettings.LocalDevelopment.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="BeatTogether.Core" Version="1.1.0" />
<PackageReference Include="BeatTogether.Core" Version="1.2.0" />
<PackageReference Include="BeatTogether.Extensions.Serilog" Version="2.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.29" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
using System;
using System.Collections.Generic;
using BeatTogether.Core.Enums;
using BeatTogether.Core.Models;
using BeatTogether.MasterServer.Api.Util;

namespace BeatTogether.MasterServer.Api.Configuration
{
public class ApiServerConfiguration
public sealed class ApiServerConfiguration
{
public int SessionTimeToLive { get; set; } = 180;
public bool AuthenticateClients { get; set; } = true;
public HashSet<VersionRange> VersionRanges { get; set; } = new();
public HashSet<Platform> AuthedClients { get; set; } = new();
}
}
13 changes: 10 additions & 3 deletions BeatTogether.MasterServer.Api/Extensions/HostBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
using BeatTogether.MasterServer.Api.Implementations;
using BeatTogether.MasterServer.Api.Implimentations;
using BeatTogether.MasterServer.Kernel.Implementations.Providers;
using BinaryRecords.Extensions;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Rewrite;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

Expand Down Expand Up @@ -38,9 +40,14 @@ public static IHostBuilder UseMasterServerApi(this IHostBuilder hostBuilder) =>
)
.Configure(applicationBuilder =>
applicationBuilder
.UseRouting()
.Use((context, next) =>
{
context.Response.Headers.Add("X-Robots-Tag", "noindex, nofollow"); // Tell everyone that we don't want to be indexed
return next(context);
})
.UseRouting()
.UseEndpoints(endPointRouteBuilder => endPointRouteBuilder.MapControllers())
)
);
)
);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using BeatTogether.MasterServer.Messaging.Enums;
using BeatTogether.MasterServer.Messaging.Models;
Expand All @@ -10,8 +11,10 @@
using BeatTogether.MasterServer.Api.Abstractions;
using BeatTogether.MasterServer.Api.Util;
using System.Text;
using BeatTogether.Core.Models;
using BeatTogether.MasterServer.Domain.Models;
using BeatTogether.MasterServer.Api.Abstractions.Providers;
using BeatTogether.MasterServer.Api.Configuration;

namespace BeatTogether.MasterServer.Api.HttpControllers
{
Expand All @@ -30,21 +33,25 @@ public class GetMultiplayerInstanceController : Controller

private readonly ILayer2 _layer2;

public GetMultiplayerInstanceController(
private readonly ApiServerConfiguration _apiServerConfiguration;

public GetMultiplayerInstanceController(
IMasterServerSessionService sessionService,
ILayer2 layer2,
IServerCodeProvider serverCodeProvider,
ISecretProvider secretProvider,
IUserAuthenticator userAuthenticator)
IUserAuthenticator userAuthenticator,
ApiServerConfiguration configuration)
{
_layer2 = layer2;
_sessionService = sessionService;
_serverCodeProvider = serverCodeProvider;
_secretProvider = secretProvider;
_userAuthenticator = userAuthenticator;


_logger = Log.ForContext<GetMultiplayerInstanceController>();
_apiServerConfiguration = configuration;

_logger = Log.ForContext<GetMultiplayerInstanceController>();
}

/// <summary>
Expand All @@ -57,8 +64,6 @@ public async Task<IActionResult> GetMultiplayerInstance([FromBody] GetMultiplaye
var response = new GetMultiplayerInstanceResponse();
response.AddRequestContext(request);

// TODO Validate game client version supported range?

if (HttpContext.Connection.RemoteIpAddress is null)
{
_logger.Warning("Auth failure: Missing IP address from HTTP request context");
Expand Down Expand Up @@ -104,8 +109,25 @@ public async Task<IActionResult> GetMultiplayerInstance([FromBody] GetMultiplaye
//if(session == null) { _logger.Information("Player Session is null"); }
response.AddSessionContext(session.PlayerSessionId);

//Player authed and has a session, now get them a server.
bool isQuickplay = string.IsNullOrEmpty(request.PrivateGameCode) && string.IsNullOrEmpty(request.PrivateGameSecret); //Quickplay is true if there is no code and no secret
// Get version range of player
VersionRange supportedRange = VersionRange.FindVersionRange(_apiServerConfiguration.VersionRanges.ToList(), session.PlayerClientVersion!);
if (supportedRange == null)
{
// Version not supported at all according to config
_logger.Error($"Could not find matching version range for client version: {session.PlayerClientVersion}");
response.ErrorCode = MultiplayerPlacementErrorCode.GameVersionUnknown;
return new JsonResult(response);
}

//if (supportedRange != null) // TODO: Should we just set to exact version match if not known?
// supportedRange = new VersionRange
// { MinVersion = session.PlayerClientVersion.ToString(), MaxVersion = session.PlayerClientVersion.ToString() };

_logger.Debug(
$"Found version range MinVersion: '{supportedRange.MinVersion}' MaxVersion: '{supportedRange.MaxVersion}' for client version '{session.PlayerClientVersion}'");

//Player authed and has a session, now get them a server.
bool isQuickplay = string.IsNullOrEmpty(request.PrivateGameCode) && string.IsNullOrEmpty(request.PrivateGameSecret); //Quickplay is true if there is no code and no secret
IServerInstance server = null;
if (!isQuickplay)
{
Expand All @@ -123,7 +145,8 @@ public async Task<IActionResult> GetMultiplayerInstance([FromBody] GetMultiplaye
(Core.Enums.GameplayServerControlSettings)request.GameplayServerConfiguration.GameplayServerControlSettings,
(Core.Enums.BeatmapDifficultyMask)request.BeatmapLevelSelectionMask.BeatmapDifficultyMask,
(Core.Enums.GameplayModifiersMask)request.BeatmapLevelSelectionMask.GameplayModifiersMask,
request.BeatmapLevelSelectionMask.SongPackMasks);
request.BeatmapLevelSelectionMask.SongPackMasks,
supportedRange);
}

//If the server is still null, then make new server
Expand All @@ -144,13 +167,13 @@ public async Task<IActionResult> GetMultiplayerInstance([FromBody] GetMultiplaye
string secret = request.PrivateGameSecret;
string managerId = FixedServerUserId;
if (!isQuickplay)
managerId = session.HashedUserId;//sets the manager to the player who is requesting
managerId = session.HashedUserId; //sets the manager to the player who is requesting
else
secret = _secretProvider.GetSecret();

string ServerName = string.Empty;
if (isQuickplay)
ServerName = "BeatTogether Quickplay: " + ((Core.Enums.BeatmapDifficultyMask)request.BeatmapLevelSelectionMask.BeatmapDifficultyMask).ToString();
ServerName = "BeatTogether Quickplay: " + ((Core.Enums.BeatmapDifficultyMask)request.BeatmapLevelSelectionMask.BeatmapDifficultyMask);
else if (request.ExtraServerConfiguration != null && request.ExtraServerConfiguration.ServerName != null)
{
ServerName = request.ExtraServerConfiguration.ServerName;
Expand Down Expand Up @@ -184,7 +207,8 @@ public async Task<IActionResult> GetMultiplayerInstance([FromBody] GetMultiplaye
ServerStartJoinTimeout = 10000L,
//ServerStartJoinTimeout = request.ExtraServerConfiguration.Timeout ?? 10, //Dont allow everyone to do this as -1 means infinite server online time, server wont turn off when a player leaves
PermanentManager = request.ExtraServerConfiguration != null ? request.ExtraServerConfiguration.PermenantManger ?? true : true,
};
SupportedVersionRange = supportedRange
};
//Missing values from the server instance such as endpoint, will be added from within the CreateInstance function below.
if (!await _layer2.CreateInstance(server))
{
Expand All @@ -203,7 +227,29 @@ public async Task<IActionResult> GetMultiplayerInstance([FromBody] GetMultiplaye
return new JsonResult(response);
}

_logger.Information("Player session data from player: " + session.HashedUserId + " Is being sent to node: " + server.InstanceEndPoint + ", Server secret: " + server.Secret + ", Player count before join: " + server.PlayerHashes.Count);
// Checks if the joining players version is witin the supported range of the lobby
switch (VersionRange.CheckVersionRange(server.SupportedVersionRange, session.PlayerClientVersion))
{
case VersionRange.VersionStatus.Ok:
break;
case VersionRange.VersionStatus.TooHigh:
_logger.Warning($"Player '{session.HashedUserId}' on version '{session.PlayerClientVersion}' cannot join lobby with range {server.SupportedVersionRange.MinVersion} - {server.SupportedVersionRange.MaxVersion} reason: Game Version Too New");
response.ErrorCode = MultiplayerPlacementErrorCode.GameVersionTooNew;
return new JsonResult(response);
case VersionRange.VersionStatus.TooLow:
_logger.Warning($"Player '{session.HashedUserId}' on version '{session.PlayerClientVersion}' cannot join lobby with range {server.SupportedVersionRange.MinVersion} - {server.SupportedVersionRange.MaxVersion} reason: Game Version Too Old");
response.ErrorCode = MultiplayerPlacementErrorCode.GameVersionTooOld;
return new JsonResult(response);
}
//if (!VersionRange.VersionRangeSatisfies(server.SupportedVersionRange,
// session.PlayerClientVersion.ToString()))
//{
// _logger.Warning($"Player '{session.HashedUserId}' on version '{session.PlayerClientVersion}' cannot join lobby with range {server.SupportedVersionRange.MinVersion} - {server.SupportedVersionRange.MaxVersion}");
// response.ErrorCode = MultiplayerPlacementErrorCode.LobbyHostVersionMismatch;
// return new JsonResult(response);
//}

_logger.Information("Player session data from player: " + session.HashedUserId + " Is being sent to node: " + server.InstanceEndPoint + ", Server secret: " + server.Secret + ", Player count before join: " + server.PlayerHashes.Count);

if (!await _layer2.SetPlayerSessionData(server.Secret, session))
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.Json;
Expand Down Expand Up @@ -146,14 +147,8 @@ public async Task<bool> TryAuthenticateUserWithPlatform(MasterServerSession sess

private bool GetPlatformRequiresAuth(Platform platform)
{
return platform switch
{
Platform.Steam => true,
Platform.OculusQuest => true,
Platform.Oculus => true,
Platform.Pico => false, // TODO: Pico auth, if possible
_ => false,
};
_logger.Debug("Authed Platforms: " + string.Join(", ", _apiServerConfiguration.AuthedClients));
return _apiServerConfiguration.AuthedClients.Contains(platform);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Net;
using System.Threading.Tasks;
using BeatTogether.Core.Enums;
using BeatTogether.Core.Models;
using BeatTogether.MasterServer.Domain.Models;

namespace BeatTogether.MasterServer.Data.Abstractions.Repositories
Expand All @@ -10,14 +11,15 @@ public interface IServerRepository
Task<Server> GetServer(string secret);
Task<Server> GetServerByCode(string code);
Task<Server> GetAvailablePublicServer(
InvitePolicy invitePolicy,
GameplayServerMode serverMode,
SongSelectionMode songMode,
GameplayServerControlSettings serverControlSettings,
BeatmapDifficultyMask difficultyMask,
GameplayModifiersMask modifiersMask,
string SongPackMasks);
Task<bool> UpdateServer(string secret, Server server);
InvitePolicy invitePolicy,
GameplayServerMode serverMode,
SongSelectionMode songMode,
GameplayServerControlSettings serverControlSettings,
BeatmapDifficultyMask difficultyMask,
GameplayModifiersMask modifiersMask,
string SongPackMasks,
VersionRange versionRange);
Task<bool> UpdateServer(string secret, Server server);
Task<string[]> GetPublicServerSecrets();
Task<string[]> GetPublicServerCodes();
Task<Server[]> GetPublicServerList();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using System.Collections.Concurrent;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using BeatTogether.MasterServer.Data.Abstractions.Repositories;
using BeatTogether.Core.Enums;
using BeatTogether.Core.Models;
using BeatTogether.MasterServer.Domain.Models;

namespace BeatTogether.MasterServer.Data.Implementations.Repositories
Expand Down Expand Up @@ -96,28 +98,29 @@ public Task<Server> GetServerByCode(string code)
}

public Task<Server> GetAvailablePublicServer(
InvitePolicy invitePolicy,
GameplayServerMode serverMode,
SongSelectionMode songMode,
GameplayServerControlSettings serverControlSettings,
BeatmapDifficultyMask difficultyMask,
GameplayModifiersMask modifiersMask,
string SongPackMasks)
{
if (!_servers.Any())
return Task.FromResult<Server>(null);
//Search for public server that fits the filter
var publicServers = _servers.Values.Where(server =>
server.GameplayServerConfiguration.DiscoveryPolicy == DiscoveryPolicy.Public &&
server.GameplayServerConfiguration.InvitePolicy == invitePolicy &&
server.GameplayServerConfiguration.GameplayServerMode == serverMode &&
server.GameplayServerConfiguration.SongSelectionMode == songMode &&
server.GameplayServerConfiguration.GameplayServerControlSettings == serverControlSettings &&
server.BeatmapDifficultyMask == difficultyMask &&
server.GameplayModifiersMask == modifiersMask &&
server.SongPackMasks == SongPackMasks &&
InvitePolicy invitePolicy,
GameplayServerMode serverMode,
SongSelectionMode songMode,
GameplayServerControlSettings serverControlSettings,
BeatmapDifficultyMask difficultyMask,
GameplayModifiersMask modifiersMask,
string SongPackMasks,
VersionRange versionRange)
{
if (!_servers.Any())
return Task.FromResult<Server>(null);
var publicServers = _servers.Values.Where(server =>
server.GameplayServerConfiguration.DiscoveryPolicy == DiscoveryPolicy.Public &&
server.GameplayServerConfiguration.InvitePolicy == invitePolicy &&
server.GameplayServerConfiguration.GameplayServerMode == serverMode &&
server.GameplayServerConfiguration.SongSelectionMode == songMode &&
server.GameplayServerConfiguration.GameplayServerControlSettings == serverControlSettings &&
server.BeatmapDifficultyMask == difficultyMask &&
server.GameplayModifiersMask == modifiersMask &&
server.SongPackMasks == SongPackMasks &&
server.SupportedVersionRange == versionRange &&
server.CurrentPlayerCount <= server.GameplayServerConfiguration.MaxPlayerCount
);
);
if (!publicServers.Any())
return Task.FromResult<Server>(null);
var server = publicServers.First();
Expand All @@ -132,7 +135,8 @@ public Task<Server> GetAvailablePublicServer(
return Task.FromResult(server);
}

public Task<bool> AddServer(Server server)

public Task<bool> AddServer(Server server)
{
if (!_servers.TryAdd(server.Secret, server))
return Task.FromResult(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ public async Task<Server> GetAvailablePublicServer(InvitePolicy invitePolicy,
GameplayServerControlSettings serverControlSettings,
BeatmapDifficultyMask difficultyMask,
GameplayModifiersMask modifiersMask,
string SongPackMasks)
string SongPackMasks,
VersionRange versionRange)
{
var database = _connectionMultiplexer.GetDatabase();
var redisValues = await database.SortedSetRangeByScoreAsync(RedisKeys.PublicServersByPlayerCount, take: 1);
Expand Down Expand Up @@ -132,6 +133,7 @@ public async Task<bool> AddServer(Server server)
currentPlayerCount = (RedisValue)server.CurrentPlayerCount,
//random = (RedisValue)server.Random,
//publicKey = (RedisValue)server.PublicKey
//SupportedVersionRange = (RedisValue)()
},
flags: CommandFlags.DemandMaster
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BeatTogether.Core" Version="1.0.3" />
<PackageReference Include="BeatTogether.Core" Version="1.2.0" />
</ItemGroup>

</Project>
5 changes: 4 additions & 1 deletion BeatTogether.MasterServer.Domain/Models/Server.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Net;
using BeatTogether.Core.Abstractions;
using BeatTogether.Core.Enums;
Expand All @@ -23,6 +24,8 @@ public Server() { }
public HashSet<string> PlayerHashes { get; set; } = new();

public string ManagerId { get; set; }

public VersionRange SupportedVersionRange { get; set; }
public bool PermanentManager { get; set; }
public long ServerStartJoinTimeout { get; set; }
public bool NeverCloseServer { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

<ItemGroup>
<PackageReference Include="Autobus.Abstractions" Version="0.1.5" />
<PackageReference Include="BeatTogether.Core" Version="1.0.3" />
<PackageReference Include="BeatTogether.Core" Version="1.2.0" />
</ItemGroup>

</Project>
Loading